| 
									
										
										
										
											2007-09-04 01:58:19 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // JavaScript for Hudson
 | 
					
						
							|  |  |  | //     See http://www.ibm.com/developerworks/web/library/wa-memleak/?ca=dgr-lnxw97JavascriptLeaks
 | 
					
						
							|  |  |  | //     for memory leak patterns and how to prevent them.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  | // create a new object whose prototype is the given object
 | 
					
						
							|  |  |  | function object(o) { | 
					
						
							|  |  |  |     function F() {} | 
					
						
							|  |  |  |     F.prototype = o; | 
					
						
							|  |  |  |     return new F(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-31 05:03:57 +08:00
										 |  |  | // id generator
 | 
					
						
							|  |  |  | var iota = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | // Form check code
 | 
					
						
							|  |  |  | //========================================================
 | 
					
						
							| 
									
										
										
										
											2007-03-12 02:19:38 +08:00
										 |  |  | var FormChecker = { | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     // pending requests
 | 
					
						
							|  |  |  |     queue : [], | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     inProgress : false, | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     delayedCheck : function(url, method, target) { | 
					
						
							|  |  |  |         this.queue.push({url:url, method:method, target:target}); | 
					
						
							|  |  |  |         this.schedule(); | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     sendRequest : function(url, params) { | 
					
						
							|  |  |  |         if (params.method == "post") { | 
					
						
							|  |  |  |             var idx = url.indexOf('?'); | 
					
						
							|  |  |  |             params.parameters = url.substring(idx + 1); | 
					
						
							|  |  |  |             url = url.substring(0, idx); | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |         new Ajax.Request(url, params); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     schedule : function() { | 
					
						
							|  |  |  |         if (this.inProgress)  return; | 
					
						
							|  |  |  |         if (this.queue.length == 0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var next = this.queue.shift(); | 
					
						
							|  |  |  |         this.inProgress = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.sendRequest(next.url, { | 
					
						
							|  |  |  |             method : next.method, | 
					
						
							|  |  |  |             onComplete : function(x) { | 
					
						
							|  |  |  |                 next.target.innerHTML = x.responseText; | 
					
						
							|  |  |  |                 FormChecker.inProgress = false; | 
					
						
							|  |  |  |                 FormChecker.schedule(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  | function findFollowingTR(input, className) { | 
					
						
							|  |  |  |     // identify the parent TR
 | 
					
						
							|  |  |  |     var tr = input; | 
					
						
							|  |  |  |     while (tr.tagName != "TR") | 
					
						
							|  |  |  |         tr = tr.parentNode; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     // then next TR that matches the CSS
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         tr = tr.nextSibling; | 
					
						
							|  |  |  |     } while (tr.tagName != "TR" || tr.className != className); | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     return tr; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  | // shared tooltip object
 | 
					
						
							|  |  |  | var tooltip; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Behavior rules
 | 
					
						
							|  |  |  | //========================================================
 | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:57 +08:00
										 |  |  | // using tag names in CSS selector makes the processing faster
 | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  | function registerValidator(e) { | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     e.targetElement = findFollowingTR(e, "validation-error-area").firstChild.nextSibling; | 
					
						
							|  |  |  |     e.targetUrl = function() { | 
					
						
							|  |  |  |         return eval(this.getAttribute("checkUrl")); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  |     var method = e.getAttribute("checkMethod"); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     if (!method) method = "get"; | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     FormChecker.delayedCheck(e.targetUrl(), method, e.targetElement); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-23 09:47:07 +08:00
										 |  |  |     var checker = function() { | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |         var target = this.targetElement; | 
					
						
							|  |  |  |         FormChecker.sendRequest(this.targetUrl(), { | 
					
						
							|  |  |  |             method : method, | 
					
						
							|  |  |  |             onComplete : function(x) { | 
					
						
							|  |  |  |                 target.innerHTML = x.responseText; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-23 09:47:07 +08:00
										 |  |  |     var oldOnchange = e.onchange; | 
					
						
							|  |  |  |     if(typeof oldOnchange=="function") { | 
					
						
							|  |  |  |         e.onchange = function() { checker.call(this); oldOnchange.call(this); } | 
					
						
							|  |  |  |     } else | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         e.onchange = checker; | 
					
						
							| 
									
										
										
										
											2007-10-23 09:47:07 +08:00
										 |  |  |     e.onblur = checker; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 01:58:19 +08:00
										 |  |  |     e = null; // avoid memory leak
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Wraps a <button> into YUI button. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param e | 
					
						
							|  |  |  |  *      button element | 
					
						
							|  |  |  |  * @param onclick | 
					
						
							|  |  |  |  *      onclick handler | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function makeButton(e,onclick) { | 
					
						
							|  |  |  |     var clsName = e.className; | 
					
						
							|  |  |  |     var btn = new YAHOO.widget.Button(e,{}); | 
					
						
							| 
									
										
										
										
											2007-10-27 22:26:11 +08:00
										 |  |  |     if(onclick!=null) | 
					
						
							|  |  |  |         btn.addListener("click",onclick); | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |     Element.addClassName(btn.get("element"),clsName); | 
					
						
							| 
									
										
										
										
											2007-11-20 01:46:08 +08:00
										 |  |  |     return btn; | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | var hudsonRules = { | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     "BODY" : function() { | 
					
						
							| 
									
										
										
										
											2007-10-29 00:28:00 +08:00
										 |  |  |         tooltip = new YAHOO.widget.Tooltip("tt", {context:[], zindex:999}); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-31 08:43:46 +08:00
										 |  |  | // do the ones that extract innerHTML so that they can get their original HTML before
 | 
					
						
							|  |  |  | // other behavior rules change them (like YUI buttons.)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "DIV.hetero-list-container" : function(e) { | 
					
						
							|  |  |  |         // components for the add button
 | 
					
						
							|  |  |  |         var menu = document.createElement("SELECT"); | 
					
						
							|  |  |  |         var btn = findElementsBySelector(e,"INPUT.hetero-list-add")[0]; | 
					
						
							|  |  |  |         YAHOO.util.Dom.insertAfter(menu,btn); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var prototypes = e.lastChild; | 
					
						
							|  |  |  |         while(!Element.hasClassName(prototypes,"prototypes")) | 
					
						
							|  |  |  |             prototypes = prototypes.previousSibling; | 
					
						
							|  |  |  |         var insertionPoint = prototypes.previousSibling;    // this is where the new item is inserted.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // extract templates
 | 
					
						
							|  |  |  |         var templates = []; var i=0; | 
					
						
							|  |  |  |         for(var n=prototypes.firstChild;n!=null;n=n.nextSibling,i++) { | 
					
						
							|  |  |  |             var name = n.getAttribute("name"); | 
					
						
							| 
									
										
										
										
											2007-11-09 09:27:04 +08:00
										 |  |  |             var tooltip = n.getAttribute("tooltip"); | 
					
						
							| 
									
										
										
										
											2007-10-31 08:43:46 +08:00
										 |  |  |             menu.options[i] = new Option(n.getAttribute("title"),""+i); | 
					
						
							| 
									
										
										
										
											2007-11-09 09:27:04 +08:00
										 |  |  |             templates.push({html:n.innerHTML, name:name, tooltip:tooltip}); | 
					
						
							| 
									
										
										
										
											2007-10-31 08:43:46 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         Element.remove(prototypes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu }); | 
					
						
							|  |  |  |         menuButton.getMenu().clickEvent.subscribe(function(type,args,value) { | 
					
						
							|  |  |  |             var t = templates[parseInt(args[1].value)]; // where this args[1] comes is a real mystery
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var nc = document.createElement("div"); | 
					
						
							|  |  |  |             nc.className = "repeated-chunk"; | 
					
						
							|  |  |  |             nc.setAttribute("name",t.name); | 
					
						
							|  |  |  |             nc.innerHTML = t.html; | 
					
						
							|  |  |  |             insertionPoint.parentNode.insertBefore(nc, insertionPoint); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Behaviour.applySubtree(nc); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-11-09 09:27:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         menuButton.getMenu().renderEvent.subscribe(function(type,args,value) { | 
					
						
							|  |  |  |             // hook up tooltip for menu items
 | 
					
						
							|  |  |  |             var items = menuButton.getMenu().getItems(); | 
					
						
							|  |  |  |             for(i=0; i<items.length; i++) { | 
					
						
							|  |  |  |                 var t = templates[i].tooltip; | 
					
						
							|  |  |  |                 if(t!=null) | 
					
						
							|  |  |  |                     applyTooltip(items[i].element,t); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-10-31 08:43:46 +08:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "DIV.repeated-container" : function(e) { | 
					
						
							|  |  |  |         // compute the insertion point
 | 
					
						
							|  |  |  |         var ip = e.lastChild; | 
					
						
							|  |  |  |         while (!Element.hasClassName(ip, "repeatable-insertion-point")) | 
					
						
							|  |  |  |             ip = ip.previousSibling; | 
					
						
							|  |  |  |         // set up the logic
 | 
					
						
							|  |  |  |         object(repeatableSupport).init(e, e.firstChild, ip); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 07:19:56 +08:00
										 |  |  |     "TABLE.sortable" : function(e) {// sortable table
 | 
					
						
							|  |  |  |         ts_makeSortable(e); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-06 14:10:35 +08:00
										 |  |  |     "TABLE.progress-bar" : function(e) {// sortable table
 | 
					
						
							|  |  |  |         e.onclick = function() { | 
					
						
							|  |  |  |             var href = this.getAttribute("href"); | 
					
						
							| 
									
										
										
										
											2007-09-06 14:38:21 +08:00
										 |  |  |             if(href!=null)      window.location = href; | 
					
						
							| 
									
										
										
										
											2007-09-06 14:10:35 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         e = null; // avoid memory leak
 | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     "INPUT.advancedButton" : function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         makeButton(e,function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-27 22:26:11 +08:00
										 |  |  |             var link = e.target; | 
					
						
							|  |  |  |             while(!Element.hasClassName(link,"advancedLink")) | 
					
						
							|  |  |  |                 link = link.parentNode; | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             link.style.display = "none"; // hide the button
 | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             var container = link.nextSibling.firstChild; // TABLE -> TBODY
 | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             var tr = link; | 
					
						
							|  |  |  |             while (tr.tagName != "TR") | 
					
						
							|  |  |  |                 tr = tr.parentNode; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             // move the contents of the advanced portion into the main table
 | 
					
						
							| 
									
										
										
										
											2007-11-08 10:27:47 +08:00
										 |  |  |             var nameRef = tr.getAttribute("nameref"); | 
					
						
							|  |  |  |             while (container.lastChild != null) { | 
					
						
							|  |  |  |                 var row = container.lastChild; | 
					
						
							|  |  |  |                 if(nameRef!=null) | 
					
						
							|  |  |  |                     row.setAttribute("nameref",nameRef); | 
					
						
							|  |  |  |                 tr.parentNode.insertBefore(row, tr.nextSibling); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |         e = null; // avoid memory leak
 | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  | // scripting for having default value in the input field
 | 
					
						
							|  |  |  |     "INPUT.has-default-text" : function(e) { | 
					
						
							|  |  |  |         var defaultValue = e.value; | 
					
						
							|  |  |  |         Element.addClassName(e, "defaulted"); | 
					
						
							|  |  |  |         e.onfocus = function() { | 
					
						
							|  |  |  |             if (this.value == defaultValue) { | 
					
						
							|  |  |  |                 this.value = ""; | 
					
						
							| 
									
										
										
										
											2007-09-04 07:35:22 +08:00
										 |  |  |                 Element.removeClassName(this, "defaulted"); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e.onblur = function() { | 
					
						
							|  |  |  |             if (this.value == "") { | 
					
						
							|  |  |  |                 this.value = defaultValue; | 
					
						
							| 
									
										
										
										
											2007-09-04 07:35:22 +08:00
										 |  |  |                 Element.addClassName(this, "defaulted"); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e = null; // avoid memory leak
 | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  | // <label> that doesn't use ID, so that it can be copied in <repeatable>
 | 
					
						
							|  |  |  |     "LABEL.attach-previous" : function(e) { | 
					
						
							|  |  |  |         e.onclick = function() { | 
					
						
							|  |  |  |             var e = this; | 
					
						
							|  |  |  |             while(e.tagName!="INPUT") | 
					
						
							|  |  |  |                 e=e.previousSibling; | 
					
						
							|  |  |  |             e.click(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e = null; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  | // form fields that are validated via AJAX call to the server
 | 
					
						
							|  |  |  | // elements with this class should have two attributes 'checkUrl' that evaluates to the server URL.
 | 
					
						
							|  |  |  |     "INPUT.validated" : registerValidator, | 
					
						
							|  |  |  |     "SELECT.validated" : registerValidator, | 
					
						
							|  |  |  |     "TEXTAREA.validated" : registerValidator, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // validate form values to be a number
 | 
					
						
							|  |  |  |     "INPUT.number" : function(e) { | 
					
						
							|  |  |  |         e.targetElement = findFollowingTR(e, "validation-error-area").firstChild.nextSibling; | 
					
						
							|  |  |  |         e.onchange = function() { | 
					
						
							|  |  |  |             if (this.value.match(/^(\d+|)$/)) { | 
					
						
							|  |  |  |                 this.targetElement.innerHTML = ""; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 this.targetElement.innerHTML = "<div class=error>Not a number</div>"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e = null; // avoid memory leak
 | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     "A.help-button" : function(e) { | 
					
						
							|  |  |  |         e.onclick = function() { | 
					
						
							|  |  |  |             var tr = findFollowingTR(this, "help-area"); | 
					
						
							|  |  |  |             var div = tr.firstChild.nextSibling.firstChild; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             if (div.style.display != "block") { | 
					
						
							|  |  |  |                 div.style.display = "block"; | 
					
						
							| 
									
										
										
										
											2007-10-30 05:27:50 +08:00
										 |  |  |                 // make it visible
 | 
					
						
							| 
									
										
										
										
											2007-10-30 05:28:16 +08:00
										 |  |  |                 new Ajax.Request(this.getAttribute("helpURL"), { | 
					
						
							|  |  |  |                     method : 'get', | 
					
						
							|  |  |  |                     onComplete : function(x) { | 
					
						
							|  |  |  |                         div.innerHTML = x.responseText; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 div.style.display = "none"; | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e = null; // avoid memory leak
 | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // deferred client-side clickable map.
 | 
					
						
							|  |  |  | // this is useful where the generation of <map> element is time consuming
 | 
					
						
							|  |  |  |     "IMG[lazymap]" : function(e) { | 
					
						
							|  |  |  |         new Ajax.Request( | 
					
						
							|  |  |  |             e.getAttribute("lazymap"), | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 method : 'get', | 
					
						
							|  |  |  |                 onComplete : function(x) { | 
					
						
							|  |  |  |                     var div = document.createElement("div"); | 
					
						
							|  |  |  |                     document.body.appendChild(div); | 
					
						
							|  |  |  |                     div.innerHTML = x.responseText; | 
					
						
							|  |  |  |                     var id = "map" + (iota++); | 
					
						
							|  |  |  |                     div.firstChild.setAttribute("name", id); | 
					
						
							|  |  |  |                     e.setAttribute("usemap", "#" + id); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // button to add a new repeatable block
 | 
					
						
							|  |  |  |     "INPUT.repeatable-add" : function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         makeButton(e,function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-29 00:40:49 +08:00
										 |  |  |             repeatableSupport.onAdd(e.target); | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-09-04 01:58:19 +08:00
										 |  |  |         e = null; // avoid memory leak
 | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "INPUT.repeatable-delete" : function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         makeButton(e,function(e) { | 
					
						
							| 
									
										
										
										
											2007-10-29 00:40:49 +08:00
										 |  |  |             repeatableSupport.onDelete(e.target); | 
					
						
							| 
									
										
										
										
											2007-10-27 22:17:47 +08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-09-04 01:58:19 +08:00
										 |  |  |         e = null; // avoid memory leak
 | 
					
						
							| 
									
										
										
										
											2007-06-13 09:39:48 +08:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |     // resizable text area
 | 
					
						
							|  |  |  |     "TEXTAREA" : function(textarea) { | 
					
						
							| 
									
										
										
										
											2007-09-27 12:30:31 +08:00
										 |  |  |         var handle = textarea.nextSibling; | 
					
						
							|  |  |  |         if(handle==null || handle.className!="textarea-handle") return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var Event = YAHOO.util.Event; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |         handle.onmousedown = function(ev) { | 
					
						
							| 
									
										
										
										
											2007-09-27 12:30:31 +08:00
										 |  |  |             ev = Event.getEvent(ev); | 
					
						
							|  |  |  |             var offset = textarea.offsetHeight-Event.getPageY(ev); | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |             textarea.style.opacity = 0.5; | 
					
						
							|  |  |  |             document.onmousemove = function(ev) { | 
					
						
							| 
									
										
										
										
											2007-09-27 12:30:31 +08:00
										 |  |  |                 ev = Event.getEvent(ev); | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |                 function max(a,b) { if(a<b) return b; else return a; } | 
					
						
							| 
									
										
										
										
											2007-09-27 12:30:31 +08:00
										 |  |  |                 textarea.style.height = max(32, offset + Event.getPageY(ev)) + 'px'; | 
					
						
							|  |  |  |                 return false; | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |             }; | 
					
						
							|  |  |  |             document.onmouseup = function() { | 
					
						
							|  |  |  |                 document.onmousemove = null; | 
					
						
							|  |  |  |                 document.onmouseup = null; | 
					
						
							|  |  |  |                 textarea.style.opacity = 1; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-09-27 12:30:31 +08:00
										 |  |  |         }; | 
					
						
							|  |  |  |         handle.ondblclick = function() { | 
					
						
							|  |  |  |             textarea.style.height = ""; | 
					
						
							|  |  |  |             textarea.rows = textarea.value.split("\n").length; | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-28 12:33:44 +08:00
										 |  |  |     // structured form submission
 | 
					
						
							|  |  |  |     "FORM" : function(form) { | 
					
						
							| 
									
										
										
										
											2007-09-28 12:39:06 +08:00
										 |  |  |         // add the hidden 'json' input field, which receives the form structure in JSON
 | 
					
						
							| 
									
										
										
										
											2007-09-28 12:33:44 +08:00
										 |  |  |         var div = document.createElement("div"); | 
					
						
							|  |  |  |         div.innerHTML = "<input type=hidden name=json>"; | 
					
						
							|  |  |  |         form.appendChild(div); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         form.onsubmit = function() { buildFormTree(this) }; | 
					
						
							|  |  |  |         form = null; // memory leak prevention
 | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-21 12:27:56 +08:00
										 |  |  |     // hook up tooltip.
 | 
					
						
							|  |  |  |     //   add nodismiss="" if you'd like to display the tooltip forever as long as the mouse is on the element.
 | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  |     "[tooltip]" : function(e) { | 
					
						
							| 
									
										
										
										
											2007-11-09 09:27:04 +08:00
										 |  |  |         applyTooltip(e,e.getAttribute("tooltip")); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "INPUT.submit-button" : function(e) { | 
					
						
							|  |  |  |         makeButton(e); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function applyTooltip(e,text) { | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  |         // copied from YAHOO.widget.Tooltip.prototype.configContext to efficiently add a new element
 | 
					
						
							| 
									
										
										
										
											2007-09-05 14:50:13 +08:00
										 |  |  |         // event registration via YAHOO.util.Event.addListener leaks memory, so do it by ourselves here
 | 
					
						
							| 
									
										
										
										
											2007-10-21 12:27:56 +08:00
										 |  |  |         e.onmouseover = function(ev) { | 
					
						
							|  |  |  |             var delay = this.getAttribute("nodismiss")!=null ? 99999999 : 5000; | 
					
						
							|  |  |  |             tooltip.cfg.setProperty("autodismissdelay",delay); | 
					
						
							|  |  |  |             return tooltip.onContextMouseOver.call(this,YAHOO.util.Event.getEvent(ev),tooltip); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-09-27 23:28:37 +08:00
										 |  |  |         e.onmousemove = function(ev) { return tooltip.onContextMouseMove.call(this,YAHOO.util.Event.getEvent(ev),tooltip); } | 
					
						
							|  |  |  |         e.onmouseout  = function(ev) { return tooltip.onContextMouseOut .call(this,YAHOO.util.Event.getEvent(ev),tooltip); } | 
					
						
							| 
									
										
										
										
											2007-11-09 09:27:04 +08:00
										 |  |  |         e.title = text; | 
					
						
							| 
									
										
										
										
											2007-09-05 14:50:13 +08:00
										 |  |  |         e = null; // avoid memory leak
 | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Behaviour.register(hudsonRules); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // used by editableDescription.jelly to replace the description field with a form
 | 
					
						
							|  |  |  | function replaceDescription() { | 
					
						
							|  |  |  |     var d = document.getElementById("description"); | 
					
						
							|  |  |  |     d.firstChild.nextSibling.innerHTML = "<div class='spinner-right'>loading...</div>"; | 
					
						
							|  |  |  |     new Ajax.Request( | 
					
						
							|  |  |  |         "./descriptionForm", | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           method : 'get', | 
					
						
							|  |  |  |           onComplete : function(x) { | 
					
						
							|  |  |  |             d.innerHTML = x.responseText; | 
					
						
							| 
									
										
										
										
											2007-09-27 11:42:55 +08:00
										 |  |  |             Behaviour.applySubtree(d); | 
					
						
							| 
									
										
										
										
											2007-01-21 23:08:00 +08:00
										 |  |  |             d.getElementsByTagName("TEXTAREA")[0].focus(); | 
					
						
							| 
									
										
										
										
											2006-11-06 05:16:01 +08:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  | function applyNameRef(s,e,id) { | 
					
						
							|  |  |  |     $(id).groupingNode = true; | 
					
						
							|  |  |  |     // s contains the node itself
 | 
					
						
							|  |  |  |     for(var x=s.nextSibling; x!=e; x=x.nextSibling) | 
					
						
							|  |  |  |         x.setAttribute("nameRef",id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 08:58:19 +08:00
										 |  |  | function initOptionalBlock(sid, eid, cid) { | 
					
						
							|  |  |  |     applyNameRef($(sid),$(eid),cid); | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  |     updateOptionalBlock($(cid),false); | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // used by optionalBlock.jelly to update the form status
 | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  | //   @param c     checkbox element
 | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  | function updateOptionalBlock(c,scroll) { | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  |     // find the start TR
 | 
					
						
							|  |  |  |     var s = c; | 
					
						
							|  |  |  |     while(!s.hasClassName("optional-block-start")) | 
					
						
							|  |  |  |         s = s.parentNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var tbl = s.parentNode; | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  |     var i = false; | 
					
						
							|  |  |  |     var o = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  |     var checked = c.checked; | 
					
						
							| 
									
										
										
										
											2007-10-01 06:29:52 +08:00
										 |  |  |     var lastRow = null; | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (var j = 0; tbl.rows[j]; j++) { | 
					
						
							|  |  |  |         var n = tbl.rows[j]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  |         if (i && n.hasClassName("optional-block-end")) | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  |             o = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (i && !o) { | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  |             if (checked) { | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  |                 n.style.display = ""; | 
					
						
							| 
									
										
										
										
											2007-10-01 06:29:52 +08:00
										 |  |  |                 lastRow = n; | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  |             } else | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  |                 n.style.display = "none"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 09:26:57 +08:00
										 |  |  |         if (n==s) { | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  |             if (n.getAttribute('hasHelp') == 'true') | 
					
						
							|  |  |  |                 j++; | 
					
						
							|  |  |  |             i = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-01 06:29:52 +08:00
										 |  |  |     if(checked && scroll) { | 
					
						
							|  |  |  |         var D = YAHOO.util.Dom; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var r = D.getRegion(s); | 
					
						
							|  |  |  |         if(lastRow!=null)   r = r.union(D.getRegion(lastRow)); | 
					
						
							|  |  |  |         scrollIntoView(r); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-11-17 00:46:18 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-01-16 03:20:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Auto-scroll support for progressive log output.
 | 
					
						
							|  |  |  | //   See http://radio.javaranch.com/pascarello/2006/08/17/1155837038219.html
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | function AutoScroller(scrollContainer) { | 
					
						
							|  |  |  |     // get the height of the viewport.
 | 
					
						
							|  |  |  |     // See http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
 | 
					
						
							|  |  |  |     function getViewportHeight() { | 
					
						
							|  |  |  |         if (typeof( window.innerWidth ) == 'number') { | 
					
						
							|  |  |  |             //Non-IE
 | 
					
						
							|  |  |  |             return window.innerHeight; | 
					
						
							|  |  |  |         } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) { | 
					
						
							|  |  |  |             //IE 6+ in 'standards compliant mode'
 | 
					
						
							|  |  |  |             return document.documentElement.clientHeight; | 
					
						
							|  |  |  |         } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) { | 
					
						
							|  |  |  |             //IE 4 compatible
 | 
					
						
							|  |  |  |             return document.body.clientHeight; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |         bottomThreshold : 25, | 
					
						
							|  |  |  |         scrollContainer: scrollContainer, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         getCurrentHeight : function() { | 
					
						
							|  |  |  |             var scrollDiv = $(this.scrollContainer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (scrollDiv.scrollHeight > 0) | 
					
						
							|  |  |  |                 return scrollDiv.scrollHeight; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 if (objDiv.offsetHeight > 0) | 
					
						
							|  |  |  |                     return scrollDiv.offsetHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return null; // huh?
 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // return true if we are in the "stick to bottom" mode
 | 
					
						
							|  |  |  |         isSticking : function() { | 
					
						
							|  |  |  |             var scrollDiv = $(this.scrollContainer); | 
					
						
							|  |  |  |             var currentHeight = this.getCurrentHeight(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // when used with the BODY tag, the height needs to be the viewport height, instead of
 | 
					
						
							|  |  |  |             // the element height.
 | 
					
						
							|  |  |  |             //var height = ((scrollDiv.style.pixelHeight) ? scrollDiv.style.pixelHeight : scrollDiv.offsetHeight);
 | 
					
						
							|  |  |  |             var height = getViewportHeight(); | 
					
						
							|  |  |  |             var diff = currentHeight - scrollDiv.scrollTop - height; | 
					
						
							|  |  |  |             // window.alert("currentHeight=" + currentHeight + ",scrollTop=" + scrollDiv.scrollTop + ",height=" + height);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return diff < this.bottomThreshold; | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         scrollToBottom : function() { | 
					
						
							|  |  |  |             var scrollDiv = $(this.scrollContainer); | 
					
						
							|  |  |  |             scrollDiv.scrollTop = this.getCurrentHeight(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-01-25 23:47:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-30 22:25:33 +08:00
										 |  |  | // scroll the current window to display the given element or the region.
 | 
					
						
							|  |  |  | function scrollIntoView(e) { | 
					
						
							|  |  |  |     function calcDelta(ex1,ex2,vx1,vw) { | 
					
						
							|  |  |  |         var vx2=vx1+vw; | 
					
						
							|  |  |  |         var a; | 
					
						
							|  |  |  |         a = Math.min(vx1-ex1,vx2-ex2); | 
					
						
							|  |  |  |         if(a>0)     return -a; | 
					
						
							|  |  |  |         a = Math.min(ex1-vx1,ex2-vx2); | 
					
						
							|  |  |  |         if(a>0)     return a; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var D = YAHOO.util.Dom; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var r; | 
					
						
							|  |  |  |     if(e.tagName!=null) r = D.getRegion(e); | 
					
						
							|  |  |  |     else                r = e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var dx = calcDelta(r.left,r.right, document.body.scrollLeft, D.getViewportWidth()); | 
					
						
							|  |  |  |     var dy = calcDelta(r.top, r.bottom,document.body.scrollTop,  D.getViewportHeight()); | 
					
						
							|  |  |  |     window.scrollBy(dx,dy); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-01-25 23:47:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // used in expandableTextbox.jelly to change a input field into a text area
 | 
					
						
							|  |  |  | function expandTextArea(button,id) { | 
					
						
							|  |  |  |     button.style.display="none"; | 
					
						
							|  |  |  |     var field = document.getElementById(id); | 
					
						
							|  |  |  |     var value = field.value.replace(/ +/g,'\n'); | 
					
						
							| 
									
										
										
										
											2007-02-15 23:44:20 +08:00
										 |  |  |     var n = field; | 
					
						
							|  |  |  |     while(n.tagName!="TABLE") | 
					
						
							|  |  |  |         n = n.parentNode; | 
					
						
							|  |  |  |     n.parentNode.innerHTML = | 
					
						
							| 
									
										
										
										
											2007-01-25 23:47:33 +08:00
										 |  |  |         "<textarea rows=8 class='setting-input' name='"+field.name+"'>"+value+"</textarea>"; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-02-04 23:22:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // refresh a part of the HTML specified by the given ID,
 | 
					
						
							|  |  |  | // by using the contents fetched from the given URL.
 | 
					
						
							|  |  |  | function refreshPart(id,url) { | 
					
						
							|  |  |  |     window.setTimeout(function() { | 
					
						
							|  |  |  |         new Ajax.Request(url, { | 
					
						
							| 
									
										
										
										
											2007-02-07 10:13:37 +08:00
										 |  |  |             method: "post", | 
					
						
							| 
									
										
										
										
											2007-02-07 10:34:48 +08:00
										 |  |  |             onSuccess: function(rsp) { | 
					
						
							| 
									
										
										
										
											2007-02-04 23:22:26 +08:00
										 |  |  |                 var hist = $(id); | 
					
						
							|  |  |  |                 var p = hist.parentNode; | 
					
						
							|  |  |  |                 var next = hist.nextSibling; | 
					
						
							|  |  |  |                 p.removeChild(hist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var div = document.createElement('div'); | 
					
						
							|  |  |  |                 div.innerHTML = rsp.responseText; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  |                 var node = div.firstChild; | 
					
						
							|  |  |  |                 p.insertBefore(node, next); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:35:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-13 12:31:20 +08:00
										 |  |  |                 Behaviour.applySubtree(node); | 
					
						
							| 
									
										
										
										
											2007-09-04 03:35:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 refreshPart(id,url); | 
					
						
							| 
									
										
										
										
											2007-02-04 23:22:26 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2007-09-06 00:57:59 +08:00
										 |  |  |     }, 5000); | 
					
						
							| 
									
										
										
										
											2007-02-14 01:06:10 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |     Perform URL encode. | 
					
						
							|  |  |  |     Taken from http://www.cresc.co.jp/tech/java/URLencoding/JavaScript_URLEncoding.htm
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | function encode(str){ | 
					
						
							|  |  |  |     var s, u; | 
					
						
							|  |  |  |     var s0 = "";                // encoded str
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (var i = 0; i < str.length; i++){   // scan the source
 | 
					
						
							|  |  |  |         s = str.charAt(i); | 
					
						
							|  |  |  |         u = str.charCodeAt(i);          // get unicode of the char
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (s == " "){s0 += "+";}       // SP should be converted to "+"
 | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             if ( u == 0x2a || u == 0x2d || u == 0x2e || u == 0x5f || ((u >= 0x30) && (u <= 0x39)) || ((u >= 0x41) && (u <= 0x5a)) || ((u >= 0x61) && (u <= 0x7a))){     // check for escape
 | 
					
						
							|  |  |  |                 s0 = s0 + s;           // don't escape
 | 
					
						
							|  |  |  |             } else {                      // escape
 | 
					
						
							|  |  |  |                 if ((u >= 0x0) && (u <= 0x7f)){     // single byte format
 | 
					
						
							|  |  |  |                     s = "0"+u.toString(16); | 
					
						
							|  |  |  |                     s0 += "%"+ s.substr(s.length-2); | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                 if (u > 0x1fffff){     // quaternary byte format (extended)
 | 
					
						
							|  |  |  |                     s0 += "%" + (0xF0 + ((u & 0x1c0000) >> 18)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + ((u & 0x3f000) >> 12)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + ((u & 0xfc0) >> 6)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + (u & 0x3f)).toString(16); | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                 if (u > 0x7ff){        // triple byte format
 | 
					
						
							|  |  |  |                     s0 += "%" + (0xe0 + ((u & 0xf000) >> 12)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + ((u & 0xfc0) >> 6)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + (u & 0x3f)).toString(16); | 
					
						
							|  |  |  |                 } else {                      // double byte format
 | 
					
						
							|  |  |  |                     s0 += "%" + (0xc0 + ((u & 0x7c0) >> 6)).toString(16); | 
					
						
							|  |  |  |                     s0 += "%" + (0x80 + (u & 0x3f)).toString(16); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return s0; | 
					
						
							| 
									
										
										
										
											2007-03-11 07:51:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-12 02:19:38 +08:00
										 |  |  | // when there are multiple form elements of the same name,
 | 
					
						
							|  |  |  | // this method returns the input field of the given name that pairs up
 | 
					
						
							|  |  |  | // with the specified 'base' input element.
 | 
					
						
							|  |  |  | Form.findMatchingInput = function(base, name) { | 
					
						
							|  |  |  |     // find the FORM element that owns us
 | 
					
						
							|  |  |  |     var f = base; | 
					
						
							|  |  |  |     while (f.tagName != "FORM") | 
					
						
							|  |  |  |         f = f.parentNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var bases = Form.getInputs(f, null, base.name); | 
					
						
							|  |  |  |     var targets = Form.getInputs(f, null, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (var i=0; i<bases.length; i++) { | 
					
						
							|  |  |  |         if (bases[i] == base) | 
					
						
							|  |  |  |             return targets[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return null;        // not found
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-20 14:01:11 +08:00
										 |  |  | // used witih <dropdownList> and <dropdownListBlock> to control visibility
 | 
					
						
							|  |  |  | function updateDropDownList(sel) { | 
					
						
							|  |  |  |     // alert('Yay! '+sel.value+' '+sel.selectedIndex);
 | 
					
						
							|  |  |  |     for (var i = 0; i < sel.forms.length; i++) { | 
					
						
							|  |  |  |         var show = sel.selectedIndex == i; | 
					
						
							|  |  |  |         var f = sel.forms[i]; | 
					
						
							|  |  |  |         var td = f.start; | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             td.style.display = (show ? "" : "none"); | 
					
						
							|  |  |  |             if (td == f.end) break; | 
					
						
							|  |  |  |             td = td.nextSibling; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // code for supporting repeatable.jelly
 | 
					
						
							| 
									
										
										
										
											2007-10-29 00:40:49 +08:00
										 |  |  | var repeatableSupport = { | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |     // set by the inherited instance to the insertion point DIV
 | 
					
						
							|  |  |  |     insertionPoint: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // HTML text of the repeated chunk
 | 
					
						
							|  |  |  |     blockHTML: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // containing <div>.
 | 
					
						
							|  |  |  |     container: null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-29 11:58:25 +08:00
										 |  |  |     // block name for structured HTML
 | 
					
						
							|  |  |  |     name : null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |     // do the initialization
 | 
					
						
							|  |  |  |     init : function(container,master,insertionPoint) { | 
					
						
							|  |  |  |         this.container = $(container); | 
					
						
							|  |  |  |         this.container.tag = this; | 
					
						
							|  |  |  |         master = $(master); | 
					
						
							|  |  |  |         this.blockHTML = master.innerHTML; | 
					
						
							|  |  |  |         master.parentNode.removeChild(master); | 
					
						
							|  |  |  |         this.insertionPoint = $(insertionPoint); | 
					
						
							| 
									
										
										
										
											2007-09-29 11:58:25 +08:00
										 |  |  |         this.name = master.getAttribute("name"); | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |         this.update(); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // insert one more block at the insertion position
 | 
					
						
							|  |  |  |     expand : function() { | 
					
						
							|  |  |  |         // importNode isn't supported in IE.
 | 
					
						
							|  |  |  |         // nc = document.importNode(node,true);
 | 
					
						
							|  |  |  |         var nc = document.createElement("div"); | 
					
						
							|  |  |  |         nc.className = "repeated-chunk"; | 
					
						
							| 
									
										
										
										
											2007-10-26 08:16:40 +08:00
										 |  |  |         nc.setAttribute("name",this.name); | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |         nc.innerHTML = this.blockHTML; | 
					
						
							|  |  |  |         this.insertionPoint.parentNode.insertBefore(nc, this.insertionPoint); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Behaviour.applySubtree(nc); | 
					
						
							|  |  |  |         this.update(); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // update CSS classes associated with repeated items.
 | 
					
						
							|  |  |  |     update : function() { | 
					
						
							|  |  |  |         var children = []; | 
					
						
							|  |  |  |         for( var n=this.container.firstChild; n!=null; n=n.nextSibling ) | 
					
						
							|  |  |  |             if(Element.hasClassName(n,"repeated-chunk")) | 
					
						
							|  |  |  |                 children.push(n); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-30 14:25:18 +08:00
										 |  |  |         if(children.length==0) { | 
					
						
							|  |  |  |             // noop
 | 
					
						
							|  |  |  |         } else | 
					
						
							| 
									
										
										
										
											2007-03-26 12:44:40 +08:00
										 |  |  |         if(children.length==1) { | 
					
						
							|  |  |  |             children[0].className = "repeated-chunk first last only"; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             children[0].className = "repeated-chunk first"; | 
					
						
							|  |  |  |             for(var i=1; i<children.length-1; i++) | 
					
						
							|  |  |  |                 children[i].className = "repeated-chunk middle"; | 
					
						
							|  |  |  |             children[children.length-1].className = "repeated-chunk last"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // these are static methods that don't rely on 'this'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // called when 'delete' button is clicked
 | 
					
						
							|  |  |  |     onDelete : function(n) { | 
					
						
							|  |  |  |         while (!Element.hasClassName(n,"repeated-chunk")) | 
					
						
							|  |  |  |             n = n.parentNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var p = n.parentNode; | 
					
						
							|  |  |  |         p.removeChild(n); | 
					
						
							|  |  |  |         p.tag.update(); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // called when 'add' button is clicked
 | 
					
						
							|  |  |  |     onAdd : function(n) { | 
					
						
							|  |  |  |         while(n.tag==null) | 
					
						
							|  |  |  |             n = n.parentNode; | 
					
						
							|  |  |  |         n.tag.expand(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  | // Used by radioBlock.jelly to wire up expandable radio block
 | 
					
						
							|  |  |  | function addRadioBlock(id) { | 
					
						
							|  |  |  |     // prototype object to be duplicated for each radio button group
 | 
					
						
							|  |  |  |     var radioBlockSupport = { | 
					
						
							|  |  |  |         buttons : null, | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |         updateButtons : function() { | 
					
						
							|  |  |  |             for( var i=0; i<this.buttons.length; i++ ) | 
					
						
							|  |  |  |                 this.buttons[i](); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |         // update one block based on the status of the given radio button
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |         updateSingleButton : function(radio, blockStart, blockEnd) { | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |             var tbl = blockStart.parentNode; | 
					
						
							|  |  |  |             var i = false; | 
					
						
							|  |  |  |             var o = false; | 
					
						
							|  |  |  |             var show = radio.checked; | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |             for (var j = 0; tbl.rows[j]; j++) { | 
					
						
							|  |  |  |                 var n = tbl.rows[j]; | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |                 if (n == blockEnd) | 
					
						
							|  |  |  |                     o = true; | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |                 if (i && !o) { | 
					
						
							|  |  |  |                     if (show) | 
					
						
							|  |  |  |                         n.style.display = ""; | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         n.style.display = "none"; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |                 if (n == blockStart) | 
					
						
							|  |  |  |                     i = true; | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:15:17 +08:00
										 |  |  |     // when one radio button is clicked, we need to update foldable block for
 | 
					
						
							|  |  |  |     // other radio buttons with the same name. To do this, group all the
 | 
					
						
							|  |  |  |     // radio buttons with the same name together and hang it under the form object
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  |     var r = document.getElementById('Rb' + id); | 
					
						
							|  |  |  |     var f = r.form; | 
					
						
							|  |  |  |     var radios = f.radios; | 
					
						
							|  |  |  |     if (radios == null) | 
					
						
							|  |  |  |         f.radios = radios = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var g = radios[r.name]; | 
					
						
							|  |  |  |     if (g == null) { | 
					
						
							|  |  |  |         radios[r.name] = g = object(radioBlockSupport); | 
					
						
							|  |  |  |         g.buttons = []; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |     var s = document.getElementById("rb_s"+id); | 
					
						
							|  |  |  |     var e = document.getElementById("rb_e"+id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  |     var u = function() { | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |         g.updateSingleButton(r,s,e); | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |     applyNameRef(s,e,'Rb'+id); | 
					
						
							| 
									
										
										
										
											2007-06-06 12:13:04 +08:00
										 |  |  |     g.buttons.push(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // apply the initial visibility
 | 
					
						
							|  |  |  |     u(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // install event handlers to update visibility.
 | 
					
						
							|  |  |  |     // needs to use onclick and onchange for Safari compatibility
 | 
					
						
							|  |  |  |     r.onclick = r.onchange = function() { g.updateButtons(); }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-09 21:45:30 +08:00
										 |  |  | function updateBuildHistory(ajaxUrl,nBuild) { | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  |     $('buildHistory').headers = ["n",nBuild]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function updateBuilds() { | 
					
						
							|  |  |  |         var bh = $('buildHistory'); | 
					
						
							| 
									
										
										
										
											2007-10-09 21:45:30 +08:00
										 |  |  |         new Ajax.Request(ajaxUrl, { | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  |             requestHeaders: bh.headers, | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  |             onSuccess: function(rsp) { | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  |                 var rows = bh.rows; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 //delete rows with transitive data
 | 
					
						
							|  |  |  |                 while (rows.length > 2 && Element.hasClassName(rows[1], "transitive")) | 
					
						
							|  |  |  |                     Element.remove(rows[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // insert new rows
 | 
					
						
							|  |  |  |                 var div = document.createElement('div'); | 
					
						
							|  |  |  |                 div.innerHTML = rsp.responseText; | 
					
						
							| 
									
										
										
										
											2007-07-30 01:29:45 +08:00
										 |  |  |                 Behaviour.applySubtree(div); | 
					
						
							| 
									
										
										
										
											2007-04-06 22:23:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 var pivot = rows[0]; | 
					
						
							|  |  |  |                 var newRows = div.firstChild.rows; | 
					
						
							|  |  |  |                 for (var i = newRows.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  |                     pivot.parentNode.insertBefore(newRows[i], pivot.nextSibling); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // next update
 | 
					
						
							|  |  |  |                 bh.headers = ["n",rsp.getResponseHeader("n")]; | 
					
						
							|  |  |  |                 window.setTimeout(updateBuilds, 5000); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     window.setTimeout(updateBuilds, 5000); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-07-28 13:31:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // send async request to the given URL (which will send back serialized ListBoxModel object),
 | 
					
						
							|  |  |  | // then use the result to fill the list box.
 | 
					
						
							|  |  |  | function updateListBox(listBox,url) { | 
					
						
							|  |  |  |     new Ajax.Request(url, { | 
					
						
							|  |  |  |         method: "post", | 
					
						
							| 
									
										
										
										
											2007-09-04 00:46:13 +08:00
										 |  |  |         onSuccess: function(rsp) { | 
					
						
							| 
									
										
										
										
											2007-07-28 13:31:33 +08:00
										 |  |  |             var l = $(listBox); | 
					
						
							|  |  |  |             while(l.length>0)   l.options[0] = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var opts = eval('('+rsp.responseText+')').values; | 
					
						
							|  |  |  |             for( var i=0; i<opts.length; i++ ) { | 
					
						
							|  |  |  |                 l.options[i] = new Option(opts[i].name,opts[i].value); | 
					
						
							|  |  |  |                 if(opts[i].selected) | 
					
						
							|  |  |  |                     l.selectedIndex = i; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-10-30 06:21:03 +08:00
										 |  |  |         }, | 
					
						
							|  |  |  |         onFailure: function(rsp) { | 
					
						
							|  |  |  |             var l = $(listBox); | 
					
						
							|  |  |  |             l.options[0] = null; | 
					
						
							| 
									
										
										
										
											2007-07-28 13:31:33 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2007-08-05 09:48:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-05 13:43:17 +08:00
										 |  |  | // get the cascaded computed style value. 'a' is the style name like 'backgroundColor'
 | 
					
						
							|  |  |  | function getStyle(e,a){ | 
					
						
							|  |  |  |   if(document.defaultView && document.defaultView.getComputedStyle) | 
					
						
							|  |  |  |     return document.defaultView.getComputedStyle(e,null).getPropertyValue(a.replace(/([A-Z])/g, "-$1")); | 
					
						
							|  |  |  |   if(e.currentStyle) | 
					
						
							| 
									
										
										
										
											2007-08-05 13:44:17 +08:00
										 |  |  |     return e.currentStyle[a]; | 
					
						
							|  |  |  |   return null; | 
					
						
							| 
									
										
										
										
											2007-08-05 13:43:17 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // set up logic behind the search box
 | 
					
						
							| 
									
										
										
										
											2007-08-05 09:48:03 +08:00
										 |  |  | function createSearchBox(searchURL) { | 
					
						
							|  |  |  |     var ds = new YAHOO.widget.DS_XHR(searchURL+"suggest",["suggestions","name"]); | 
					
						
							|  |  |  |     ds.queryMatchCase = false; | 
					
						
							|  |  |  |     var ac = new YAHOO.widget.AutoComplete("search-box","search-box-completion",ds); | 
					
						
							|  |  |  |     ac.typeAhead = false; | 
					
						
							| 
									
										
										
										
											2007-08-05 13:43:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     var box   = $("search-box"); | 
					
						
							|  |  |  |     var sizer = $("search-box-sizer"); | 
					
						
							|  |  |  |     var comp  = $("search-box-completion"); | 
					
						
							|  |  |  |     var minW  = $("search-box-minWidth"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Behaviour.addLoadEvent(function(){ | 
					
						
							|  |  |  |         // make sure all three components have the same font settings
 | 
					
						
							|  |  |  |         function copyFontStyle(s,d) { | 
					
						
							|  |  |  |             var ds = d.style; | 
					
						
							|  |  |  |             ds.fontFamily = getStyle(s,"fontFamily"); | 
					
						
							|  |  |  |             ds.fontSize = getStyle(s,"fontSize"); | 
					
						
							|  |  |  |             ds.fontStyle = getStyle(s,"fontStyle"); | 
					
						
							|  |  |  |             ds.fontWeight = getStyle(s,"fontWeight"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         copyFontStyle(box,sizer); | 
					
						
							|  |  |  |         copyFontStyle(box,minW); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // update positions and sizes of the components relevant to search
 | 
					
						
							|  |  |  |     function updatePos() { | 
					
						
							|  |  |  |         function max(a,b) { if(a>b) return a; else return b; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sizer.innerHTML = box.value; | 
					
						
							|  |  |  |         var w = max(sizer.offsetWidth,minW.offsetWidth); | 
					
						
							|  |  |  |         box.style.width = | 
					
						
							|  |  |  |         comp.style.width =  | 
					
						
							|  |  |  |         comp.firstChild.style.width = (w+60)+"px"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var pos = YAHOO.util.Dom.getXY(box); | 
					
						
							|  |  |  |         pos[1] += YAHOO.util.Dom.get(box).offsetHeight + 2; | 
					
						
							|  |  |  |         YAHOO.util.Dom.setXY(comp, pos); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     updatePos(); | 
					
						
							|  |  |  |     box.onkeyup = updatePos; | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // structured form submission handling
 | 
					
						
							|  |  |  | //   see http://hudson.gotdns.com/wiki/display/HUDSON/Structured+Form+Submission
 | 
					
						
							|  |  |  | function buildFormTree(form) { | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |     try { | 
					
						
							|  |  |  |         // I initially tried to use an associative array with DOM elemnets as keys
 | 
					
						
							|  |  |  |         // but that doesn't seem to work neither on IE nor Firefox.
 | 
					
						
							|  |  |  |         // so I switch back to adding a dynamic property on DOM.
 | 
					
						
							|  |  |  |         form.formDom = {}; // root object
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var doms = []; // DOMs that we added 'formDom' for.
 | 
					
						
							|  |  |  |         doms.push(form); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function addProperty(parent,name,value) { | 
					
						
							|  |  |  |             // abc.def.ghi -> ghi
 | 
					
						
							|  |  |  |             var idx = name.lastIndexOf('.'); | 
					
						
							|  |  |  |             if(idx>=0)  name = name.substring(idx+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if(parent[name]!=null) { | 
					
						
							|  |  |  |                 if(parent[name].push==null) // is this array?
 | 
					
						
							|  |  |  |                     parent[name] = [ parent[name] ]; | 
					
						
							|  |  |  |                 parent[name].push(value); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 parent[name] = value; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |         // find the grouping parent node, which will have @name.
 | 
					
						
							|  |  |  |         // then return the corresponding object in the map
 | 
					
						
							|  |  |  |         function findParent(e) { | 
					
						
							|  |  |  |             while(e!=form) { | 
					
						
							|  |  |  |                 e = e.parentNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // this is used to create a group where no single containing parent node exists,
 | 
					
						
							|  |  |  |                 // like <optionalBlock>
 | 
					
						
							|  |  |  |                 var nameRef = e.getAttribute("nameRef"); | 
					
						
							|  |  |  |                 if(nameRef!=null) | 
					
						
							|  |  |  |                     e = $(nameRef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var name = e.getAttribute("name"); | 
					
						
							|  |  |  |                 if(name!=null) { | 
					
						
							|  |  |  |                     if(e.tagName=="INPUT" && !e.checked) | 
					
						
							|  |  |  |                         return {};  // field is not active
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     var m = e.formDom; | 
					
						
							|  |  |  |                     if(m==null) { | 
					
						
							|  |  |  |                         // this is a new grouping node
 | 
					
						
							|  |  |  |                         doms.push(e); | 
					
						
							|  |  |  |                         e.formDom = m = {}; | 
					
						
							|  |  |  |                         addProperty(findParent(e), name, m); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     return m; | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |             return form.formDom; // guaranteed non-null
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |         var jsonElement = null; | 
					
						
							| 
									
										
										
										
											2007-09-28 12:33:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |         for( var i=0; i<form.elements.length; i++ ) { | 
					
						
							|  |  |  |             var e = form.elements[i]; | 
					
						
							|  |  |  |             if(e.name=="json") { | 
					
						
							|  |  |  |                 jsonElement = e; | 
					
						
							|  |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-10-29 09:07:31 +08:00
										 |  |  |             if(e.tagName=="FIELDSET") | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             var p; | 
					
						
							|  |  |  |             var type = e.getAttribute("type"); | 
					
						
							|  |  |  |             if(type==null)  type=""; | 
					
						
							|  |  |  |             switch(type.toLowerCase()) { | 
					
						
							|  |  |  |             case "button": | 
					
						
							|  |  |  |             case "submit": | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case "checkbox": | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |                 p = findParent(e); | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |                 if(!e.groupingNode) | 
					
						
							|  |  |  |                     addProperty(p, e.name, e.checked); | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     if(e.checked) | 
					
						
							|  |  |  |                         addProperty(p, e.name, e.formDom = {}); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |             case "radio": | 
					
						
							|  |  |  |                 if(!e.checked)  break; | 
					
						
							|  |  |  |                 if(e.groupingNode) { | 
					
						
							|  |  |  |                     p = findParent(e); | 
					
						
							|  |  |  |                     addProperty(p, e.name, e.formDom = { value: e.value }); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2007-09-04 11:42:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |                 // otherwise fall through
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 p = findParent(e); | 
					
						
							|  |  |  |                 addProperty(p, e.name, e.value); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |         jsonElement.value = Object.toJSON(form.formDom); | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  |         // clean up
 | 
					
						
							|  |  |  |         for( i=0; i<doms.length; i++ ) | 
					
						
							|  |  |  |             doms[i].formDom = null; | 
					
						
							| 
									
										
										
										
											2007-09-01 22:21:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-29 09:05:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return jsonElement.value; | 
					
						
							|  |  |  |     } catch(e) { | 
					
						
							|  |  |  |         alert(e); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-03 23:28:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // this used to be in prototype.js but it must have been removed somewhere between 1.4.0 to 1.5.1
 | 
					
						
							|  |  |  | String.prototype.trim = function() { | 
					
						
							| 
									
										
										
										
											2007-09-04 03:38:52 +08:00
										 |  |  |     var temp = this; | 
					
						
							|  |  |  |     var obj = /^(\s*)([\W\w]*)(\b\s*$)/; | 
					
						
							|  |  |  |     if (obj.test(temp)) | 
					
						
							|  |  |  |         temp = temp.replace(obj, '$2'); | 
					
						
							|  |  |  |     obj = /  /g; | 
					
						
							|  |  |  |     while (temp.match(obj)) | 
					
						
							|  |  |  |         temp = temp.replace(obj, " "); | 
					
						
							|  |  |  |     return temp; | 
					
						
							| 
									
										
										
										
											2007-09-03 23:28:53 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-10-26 14:33:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var hoverNotification = (function() { | 
					
						
							|  |  |  |     var msgBox; | 
					
						
							|  |  |  |     var body; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // animation effect that automatically hide the message box
 | 
					
						
							|  |  |  |     var effect = function(overlay, dur) { | 
					
						
							|  |  |  |         var o = YAHOO.widget.ContainerEffect.FADE(overlay, dur); | 
					
						
							|  |  |  |         o.animateInCompleteEvent.subscribe(function() { | 
					
						
							|  |  |  |             window.setTimeout(function() { | 
					
						
							|  |  |  |                 msgBox.hide() | 
					
						
							|  |  |  |             }, 1500); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         return o; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function init() { | 
					
						
							|  |  |  |         if(msgBox!=null)  return;   // already initialized
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var div = document.createElement("DIV"); | 
					
						
							|  |  |  |         document.body.appendChild(div); | 
					
						
							|  |  |  |         div.innerHTML = "<div id=hoverNotification><div class=bd></div></div>"; | 
					
						
							|  |  |  |         body = $('hoverNotification'); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         msgBox = new YAHOO.widget.Overlay(body, { | 
					
						
							|  |  |  |           visible:false, | 
					
						
							|  |  |  |           width:"10em", | 
					
						
							|  |  |  |           zIndex:1000, | 
					
						
							|  |  |  |           effect:{ | 
					
						
							|  |  |  |             effect:effect, | 
					
						
							|  |  |  |             duration:0.25 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         msgBox.render(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return function(title,anchor) { | 
					
						
							|  |  |  |         init(); | 
					
						
							|  |  |  |         body.innerHTML = title; | 
					
						
							|  |  |  |         var xy = YAHOO.util.Dom.getXY(anchor); | 
					
						
							|  |  |  |         xy[0] += 48; | 
					
						
							|  |  |  |         xy[1] += anchor.offsetHeight; | 
					
						
							|  |  |  |         msgBox.cfg.setProperty("xy",xy); | 
					
						
							|  |  |  |         msgBox.show(); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | })(); |