//Javascript functions used by the FamilyWare controls
var xmlhttpNameSearch;
var nameSearchTarget;
var divNameSearch, frameNameSearch;
var nsCount = 0;
String.prototype["trim"] = function() { return this.replace(/^\s+|\s+$/g, ''); }

var browserInfo = new function() {
   // Returns information about browser capabilities
   var _isInitialized = false;
   var _isIE = false;
   var _isWebkit = false;
   var _isGecko = false;
   var _isOpera = false;
   var _hasJava = false
   var _hasActiveX = false;
   var _flashVersion = null;

   this.isIE = function() {
      if (!_isInitialized) { init(); }
      return _isIE;
   }

   this.isWebkit = function() {
      if (!_isInitialized) { init(); }
      return _isWebkit;
   }

   this.isGecko = function() {
      if (!_isInitialized) { init(); }
      return _isGecko;
   }

   this.isOpera = function() {
      if (!_isInitialized) { init(); }
      return _isOpera;
   }

   this.hasJava = function() {
      if (!_isInitialized) { init(); }
      return _hasJava;
   }

   this.getScrollPos = function() {
      // Try IE (also works in FF and Opera)
      if (typeof (document.body.scrollTop) !== "undefined") {
         return [document.body.scrollLeft, document.body.scrollTop];
      }

      // Try Gecko and Webkit browsers
      if (typeof (window.pageXOffset) !== "undefined") {
         return [window.pageXOffset, window.pageYOffset];
      }

      // Try IE again with the documentElement object. This is available when IE is running in standards compliance mode.					
      if (typeof (document.documentElement.scrollTop) !== "undefined") {
         return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
      }
      return [0, 0];
   }
   	
   this.getMousePos = function(evt) {
      if (typeof (window.event) !== "undefined") {
         var scrollPos = browserInfo.getScrollPos();
         return [event.clientX, event.clientY];
      }
      else {
         if (typeof (evt) !== "undefined" && typeof (evt.pageX) !== "undefined") {
            return [evt.pageX, evt.pageY];
         }
      }
      return [0, 0];
   }

   function init() {
      var agent = navigator.userAgent.toLowerCase();
      if (agent.indexOf("msie") > -1 && agent.indexOf("opera") === -1) {
         _isIE = true;
      }

      // Webkit browsers based on KHTML. 
      if ((agent.indexOf("khtml") > -1 || agent.indexOf("webkit") > -1) && (agent.indexOf("safari") > -1 || agent.indexOf("konqueror") > -1 || agent.indexOf("chrome") > -1)) {
         _isWebkit = true;
      }

      // Gecko browsers. Safari uses an user agent string very similar to Mozilla Firefox.
      if (agent.indexOf("mozilla") > -1 && agent.indexOf("gecko") > -1 && agent.indexOf("webkit") === -1 && agent.indexOf("khtml") === -1) {
         _isGecko = true;
      }

      if (agent.indexOf("opera") > -1) {
         _isOpera = true;
      }

      try {
         if (_isIE === false && navigator.javaEnabled) {
            if (navigator.javaEnabled()) { _hasJava = true; }
         }
      }
      catch (err) {
         // Try...catch is needed because if(navigator.javaEnabled) is not always
         // handled correctly in IE and thus may throw an Unexpected error.
         // window.alert(err.message);
      }

      if (typeof (ActiveXObject) !== "undefined") { _hasActiveX = true; }
      _isInitialized = true;
   }
   return this;
}

/**
 * Adds an event listener to a given element.
 * @param DOMElement|String Required. DOM element or element ID to add the event to.
 * @param String Required. The name of the event to attach.
 * @param Function Required. A pointer for the event handler.
 * @param Boolean Not required. Set to true to enable event capturing.  
 */
function addEvent(el, evtName, fn, capture) {
    var _el      = (typeof(el) === "string" ? $(el) : el);
    var _capture = (capture === true ? true : false);
    var _evtName = (typeof(evtName) === "string" ? evtName : "");
    
    if(_evtName === "") { return null; }    
    if(_el && _el.attachEvent) {        
        if(_evtName.substring(0,2) !== "on") { _evtName = "on" + _evtName; }    
        if(_capture) { _el.setCapture(); }            
        _el.attachEvent(_evtName, fn);
    }    
    if(_el && _el.addEventListener) {        
        if(_evtName.substring(0,2) === "on") { _evtName = _evtName.substring(2) };        
        _el.addEventListener(_evtName, fn, _capture);    
    }
}

/**
 * Removes an event listener from a given element.
 * @param DOMElement|String Required. The element the event was registered on.
 * @param String Required. Event name to remove.
 * @param Function Required. The pointer to the event handler.
 * @param Boolean Not required. If event capturing was set for the event registration.
 */
function removeEvent(el, evtName, fn, capture) {
    var _el      = (typeof(el) === "string" ? $(el) : el);
    var _evtName = (typeof(evtName) === "string" ? evtName : "");
    var _capture = (capture === true ? true : false);
    
    if(_evtName === "") { return null; }    
    if(_el && _el.detachEvent) {
        if(_evtName.substring(0,2) !== "on") { _evtName = "on" + _evtName; }
        if(_capture) { _el.releaseCapture(); }
        _el.detachEvent(_evtName, fn);
    }        
    if(_el && _el.removeEventListener) {
        if(_evtName.substring(0,2) === "on") { _evtName = _evtName.substring(2); }
        _el.removeEventListener(_evtName, fn, _capture); 
    }
}

/**
 * Creates a context menu. For a detailed description read http://wiki.yuki.nl/js_fn_ContextMenu.ashx
 */
var ContextMenu = function(config) {
	var _config          = config;
	var _cmMainEl        = null;
	var _cmWidth         = 250;
	var _callerArgs      = null;	
	var _items           = null;
	var _that            = this;
	var _rendered        = false;

	this.getElement = function() {
		return _cmMainEl;
	}

	this.show = function(callerArgs, evt) {		
		var mousePos = browserInfo.getMousePos(evt);
		
		if(_cmMainEl) {
         if(!_rendered) {
            _rendered = true;
		      document.body.appendChild(_cmMainEl);
		      addEvent(document.body, "click", function() { _that.hide(); });
         }
			_callerArgs = callerArgs;
         
			// Horizontal position
			if(document.body.clientWidth - (mousePos[0] + _cmWidth) < 0) {
					if(!browserInfo.isGecko()) {
						_cmMainEl.style.left = mousePos[0] - _cmWidth + browserInfo.getScrollPos()[0] + "px";
					}
					else {
						_cmMainEl.style.left = mousePos[0] - _cmWidth + "px";					
					}
			}
			else {
				if(!browserInfo.isGecko()) {
					_cmMainEl.style.left = mousePos[0] + browserInfo.getScrollPos()[0] + "px";
				}
				else {
					_cmMainEl.style.left = mousePos[0] + "px";				
				}
			}
			
			// Vertical position
			if(!browserInfo.isGecko()) {
				_cmMainEl.style.top = mousePos[1] + browserInfo.getScrollPos()[1] + "px";
			}
			else {
				_cmMainEl.style.top = mousePos[1] + "px";				
			}			
			_cmMainEl.style.display = "block";			
		}
		preventBubbling(evt);					
	}

	this.hide = function(evt) {
		if(_cmMainEl) {
			_cmMainEl.style.display = "none";
		}
	}		

	function init() {
		var tmpItem = null;	
		if(typeof(_config) === "object") {
		   _cmWidth = typeof(_config.width) === "number" ? _config.width : 250;
		}
		else {
			throw new Error("ContextMenu.init() failed. No valid configuration values found. Declare as follows: var t = new ContextMenu({ items: [{ labelText: 'test' },{ labelText: 'test' }] });");
		}
	   
		// Create the context menu items place holder
		_cmMainEl = document.createElement("DIV");
		_cmMainEl.className = "contextMenu";
		_cmMainEl.style.width = _cmWidth + "px";		
		_cmMainEl.style.display = "none";
		
		// Append items to the place holder
		if(_config.items instanceof Array) {
			for(x=0; x < _config.items.length; x++) {
				tmpItem = createItem(_config.items[x], x);
				if(tmpItem !== null) {
					// Add the new element to the object for later reference
					_config.items[x].el = tmpItem;
					
					// Append the item to the context menu placeholder
					_cmMainEl.appendChild(tmpItem);
				}
			}									
		}
	}

	function createItem(config, itemIndex) {
		// Creates an context menu item object. Not intended to be called directy. 'Config' must be a JSON object. The following properties are allowed:		
		// iconUrl. String. Not required. Url to the image of the icon you want displayed.
		// labelText. String. Required. The menu item text.
		// children. Object array. Not required. Child menu items.
		// onclick. Function pointer. Not required. The click event of the menu item.
		// tooltip. String. Not required. Tooltip text for the menu item.
				
		if(typeof(config) !== "object" && typeof(config) !== "string") {
			return null;
		}
		
		if(typeof(config) === "string" && config === "-") {
			// Add horizontal line to the context menu. Use a table to avoid horrible padding and margin nightmares in IE.			
			var tmp = document.createElement("TABLE");			
			tmp.setAttribute("width", "100%");
			tmp.setAttribute("cellspacing", "0");
			tmp.setAttribute("cellpadding", "0");
			tmp.style.padding = "0px";
			tmp.style.margin = "0px";			
			tmp.style.height = "1px";			
			var tmp1 = document.createElement("TBODY");
			var tmp2 = document.createElement("TR");			
			var tmp3 = document.createElement("TD");
			tmp3.style.width = "30px";			
			var tmp4 = document.createElement("TD");
			tmp4.style.width = "auto";
			
			if(!browserInfo.isWebkit()) {
				tmp4.style.backgroundColor = "#BDBDBD";
			}
			else {
				tmp4.style.borderBottom = "1px inset #BDBDBD";
			}
			
			var tmp5 = document.createElement("TD");
			tmp5.className = "contextMenuExpand";			
			tmp2.appendChild(tmp3);
			tmp2.appendChild(tmp4);
			tmp2.appendChild(tmp5);
			tmp1.appendChild(tmp2);
			tmp.appendChild(tmp1);
			return tmp;
		}
		
		var tmpContainer = document.createElement("DIV");				
		var tmpTable     = document.createElement("TABLE");
		var tmpTbody     = document.createElement("TBODY");
		var tmpTRow      = document.createElement("TR");
		var tmpTDIcon    = document.createElement("TD");
		var tmpIcon      = document.createElement("IMG");
		var tmpTDLabel   = document.createElement("TD");
		var tmpTDExpd    = document.createElement("TD");
		
		// Item container
		tmpContainer.className = "contextMenuItem";
		if(typeof(config.tooltip) === "string") {
			tmpContainer.setAttribute("title", config.tooltip);
		}
		
		tmpContainer.setAttribute("yukiCMItem", "true");
		addEvent(tmpContainer, "mouseover", cmItem_onMouseOver);
		addEvent(tmpContainer, "mouseout", cmItem_onMouseOut);

		if(typeof(config.onclick) === "function") {
			addEvent(tmpContainer, "click", function(event) {
				config.onclick(_callerArgs, _config.items[itemIndex], event);
			});
		}
						
		// Item content table
		tmpTable.setAttribute("border", "0");
		tmpTable.setAttribute("height", "20");
		tmpTable.setAttribute("width", "100%");
		tmpTable.setAttribute("cellspacing", "0");
		tmpTable.setAttribute("cellpadding", "0");
		tmpTable.style.margin = "0px 0px 0px 0px";
		tmpTable.style.padding = "0px 0px 0px 0px";
						
		// Icon
		tmpTDIcon.style.width = "24px";
		tmpTDIcon.style.verticalAlign = "top";
		if(typeof(config.iconUrl) === "string") {
			tmpTDIcon.appendChild(tmpIcon);		
			tmpIcon.width = 16;
			tmpIcon.height = 16;
			tmpIcon.src = config.iconUrl;
			
			if(!browserInfo.isIE()) {
				tmpTDIcon.style.padding = "3px 2px 2px 2px";					
			}
			
			// To avoid a browser not-found image, remove the image object altogether if the image was not found on the server.
			tmpIcon.onerror = function() { this.parentNode.removeChild(this); };			
		}
		else { tmpTDIcon.innerHTML = "&nbsp;"; }
		
		// Label text
		tmpTDLabel.className = "contextMenuItemText";
		tmpTDLabel.innerHTML = typeof(config.labelText) === "string" ? config.labelText : "&nbsp;";
						
		// Arrow for hierarchical menu structures
		tmpTDExpd.style.width = "9px";
		if(typeof(config.children) !== "undefined") {
			tmpTDExpd.className = "contextMenuExpand contextMenuExpandIcon";
		} 
		else {
			tmpTDExpd.className = "contextMenuExpand";
		}

		// Build the entire item								
		tmpTRow.appendChild(tmpTDIcon);
		tmpTRow.appendChild(tmpTDLabel);
		tmpTRow.appendChild(tmpTDExpd);
		tmpTbody.appendChild(tmpTRow);
		tmpTable.appendChild(tmpTbody);
		tmpContainer.appendChild(tmpTable);
		
		return tmpContainer;
	}

	function cmItem_onMouseOver(evt) {
		var el = typeof(window.event) !== "undefined" ? window.event.srcElement : evt.target;		
		while(el.nodeName.toLowerCase() !== "div" && el.getAttribute("yukiCMItem") !== "true") {
			el = el.parentNode;
		}		
		el.className = "contextMenuItem contextMenuItemOver";
	}

	function cmItem_onMouseOut(evt) {
		var el = typeof(window.event) !== "undefined" ? window.event.srcElement : evt.target;		
		while(el.nodeName.toLowerCase() !== "div" && el.getAttribute("yukiCMItem") !== "true") {
			el = el.parentNode;
		}		
		el.className = "contextMenuItem";				
	}			

	init();
	return this;
}
		
var popupFrame = new function() {
	// Hides all body content behind a semi-transparent layer and opens a page mid-center in an Iframe.
	// - Create the frame: popupFrame.show("http://www.yuki.nl");
	// - Remove the frame: popupFrame.close();
	// - Recalculate position and size: popupFrame.resize();
	// - or use auto resize: popupFrame.show("http://www.yuki.nl", true);
	var _autoResize = false;
	var _evtAttached = false
	var _resultValue = null;
	var _callbackFn = null;
	var _that = this;
	var _domEl = null;
	var _supportEl = null;
	
	this.showEl = function(el, autoResize, callbackFn) {	
		_domEl = (typeof(el) === "string" ? $(el) : el);
		_ifr = document.createElement("IFRAME");
	
		if(autoResize === true) { _autoResize = true; }		
		if(typeof(callbackFn) === "function") { _callbackFn = callbackFn; }

		// Check if there's already a popupFrame created:
		if(document.getElementById("maskLayer")) { this.close(); }
		
		_domEl.style.position = "absolute";
		var tmpLayer = getMaskLayer(true);
		var elWidth = extractNumbers(_domEl.style.width);
		var elHeight = extractNumbers(_domEl.style.height);
		
		if(elWidth == 0) { elWidth = Math.floor(document.body.clientWidth * .50); }		
		if(elHeight == 0) { elHeight = Math.floor(document.body.clientHeight * .50); }
								
		var elTop = Math.floor(elHeight / 2) + parseInt(document.body.scrollTop);
		var elLeft = Math.floor(elWidth / 2) + parseInt(document.body.scrollLeft);

		_supportEl = $('ifr' + _domEl.id);
		if(!_supportEl) {
		   _supportEl = document.createElement("IFRAME");
		   _supportEl.id = 'ifr' + _domEl.id;
		   document.body.appendChild(_supportEl);
		}
		_supportEl.style.display = "block";
		_supportEl.border = 0;
		_supportEl.style.position = "absolute";
		_supportEl.style.width = elWidth;
		_supportEl.style.height = elHeight;
		_supportEl.style.top = "50%";
		_supportEl.style.left = "50%";
		_supportEl.style.marginLeft = "-" + elLeft + "px";
		_supportEl.style.marginTop = "-" + elTop + "px";
		_supportEl.src="blank.htm";
		_supportEl.style.zIndex = 50;
		_domEl.style.display = "block";		
		_domEl.style.position = "absolute";
		_domEl.style.height = (elHeight + 2) + "px";
		_domEl.style.width = (elWidth + 2) + "px";
		_domEl.style.top = "50%";
		_domEl.style.left = "50%";
		_domEl.style.marginLeft = "-" + elLeft + "px";
		_domEl.style.marginTop = "-" + elTop + "px";
		_domEl.style.zIndex = 1000;
		// Attach event to document.body if auto resize is set.
		if(_autoResize && !_evtAttached) {
			addEvent(window, "resize", function(event) { _that.resize(event); });			
			_evtAttached = true;
		}		
		document.body.style.overflow = "hidden";
		document.body.appendChild(tmpLayer);
		
		// To prevent the focus is set on an underlying object
		// set the focus to the first input control we can find:
		var inputs = _domEl.getElementsByTagName("INPUT");
		if(inputs && inputs.length > 0) {
		   try {
		      inputs[0].focus();
		   } catch(e) { }
		}
						
	}
	
	this.show = function(url, autoResize, callbackFn, evt) {
		var theUrl = (url.indexOf("?") > -1 ? url + "&closePopupFrame=true" : url + "?closePopupFrame=true");
		if(autoResize === true) { _autoResize = true; }		
		if(typeof(callbackFn) === "function") { _callbackFn = callbackFn; }

		// Check if there's already a popupFrame created:
		if(document.getElementById("maskLayer")) { this.close(); }
		
		// Create mask layer
		var tmpLayer = document.createElement("DIV");
		tmpLayer.id = "maskLayer";
		tmpLayer.style.width = "5000px";
		tmpLayer.style.height = "5000px";
		tmpLayer.style.backgroundImage = "url(images/transparent_50.png)";
		tmpLayer.style.backgroundRepeat = "repeat";
		tmpLayer.style.position = "absolute";
		tmpLayer.style.top = "0px";
		tmpLayer.style.left = "0px";
		tmpLayer.style.zIndex = 999;
		tmpLayer.style.textAlign = "left";
		tmpLayer.style.verticalAlign = "middle";
		tmpLayer.onclick = this.close;
		
		// Calculate visible area dimensions (IE)
		var ifrWidth = document.body.clientWidth * .95;
		var ifrHeight = document.body.clientHeight * .95;
		var ifrTop = (document.body.clientHeight - ifrHeight) / 2 + parseInt(document.body.scrollTop)
		var ifrLeft = (document.body.clientWidth - ifrWidth) / 2 + parseInt(document.body.scrollLeft);
		
		// Create and position the Iframe
		var tmpIFrame = document.createElement("IFRAME");
		tmpIFrame.id = "ifrMaskedPreview";
		tmpIFrame.frameBorder = "0";
		tmpIFrame.style.position = "absolute";
		tmpIFrame.style.zIndex = 9999;
		tmpIFrame.style.top = ifrTop + "px";
		tmpIFrame.style.left = ifrLeft + "px";
		tmpIFrame.style.width = ifrWidth + "px";
		tmpIFrame.style.height = ifrHeight + "px";
		tmpIFrame.style.border = "2px solid #C3DAF9";
		tmpIFrame.src = theUrl;
		
		// Prevent scrolling and append object to the body.
		// Both the layer and iframe are absolute positioned
		// with an high z-index value to keep them on top of everything
		// in the document. Keep in mind to keep the z-index 
		// values of other HTML elements below 999
		document.body.style.overflow = "hidden";
		document.body.appendChild(tmpLayer);
		document.body.appendChild(tmpIFrame);			
	
		// Attach event to document.body if auto resize is set.
		if(_autoResize && !_evtAttached) {
			addEvent(window, "resize", function() { _that.resize(event); });			
			_evtAttached = true;
		}
	}
	
	this.resize = function(event) {
		// Resizes and repositions the layer and frame element.
		var ifr = document.getElementById("ifrMaskedPreview");
		if(ifr) {
			var ifrWidth = document.body.clientWidth * .95;
			var ifrHeight = document.body.clientHeight * .95;
			var ifrTop = (document.body.clientHeight - ifrHeight) / 2 + parseInt(document.body.scrollTop);
			var ifrLeft = (document.body.clientWidth - ifrWidth) / 2 + parseInt(document.body.scrollLeft);				

			ifr.style.top = ifrTop + "px";
			ifr.style.left = ifrLeft + "px";
			ifr.style.width = ifrWidth + "px";
			ifr.style.height = ifrHeight + "px";
		}
	}
	
	this.close = function() {
		// Method to destroy the popupFrame elements
		if(document.getElementById("maskLayer")) {
			document.body.removeChild(document.getElementById("maskLayer"));			
			var ifr = $('ifrMaskedPreview');
			if(ifr) { document.body.removeChild(ifr);	}			
			if(_domEl) { _domEl.style.display = "none"; }			
			if(_supportEl) { _supportEl.style.display = "none"; }			
			document.body.style.overflow = "";					
		}
	}
	
	this.result = function(resultValue) {
		if(typeof(resultValue) !== "undefined") {
			_resultValue = resultValue;
			if(typeof(_callbackFn) === "function") { _callbackFn(resultValue); }
		}
		else { return _resultValue; }
	}
	
	function getMaskLayer(autoClose) {
		// Create mask layer
		var tmpLayer = document.createElement("DIV");
		tmpLayer.id = "maskLayer";
		tmpLayer.style.width = "5000px";
		tmpLayer.style.height = "5000px";
		tmpLayer.style.backgroundImage = "url(images/transparent_50.png)";
		tmpLayer.style.backgroundRepeat = "repeat";
		tmpLayer.style.position = "absolute";
		tmpLayer.style.top = "0px";
		tmpLayer.style.left = "0px";
		tmpLayer.style.zIndex = 999;
		tmpLayer.style.textAlign = "left";
		tmpLayer.style.verticalAlign = "middle";
		if(autoClose === true) { tmpLayer.onclick = this.close; }
		return tmpLayer;	
	}
	return this;
}

/**
 * Cross browser convenience function to prevent events from bubbling up the element hierarchy.
 *   Also prevents the default value/action for that event.
 * @param Event Not required. Normally this parameter is supplied by the browser.
 * @usage <div onclick="javascript:moveSomeStuff(this);preventBubbling(event);">Click here</div>
 */
function preventBubbling(e) {
	if(typeof(window.event) === "undefined") {
		e.stopPropagation();
	}
	else {
		window.event.cancelBubble = true;
		window.event.returnValue = false;					
	}
	// Prevent the event from bubbling
	if(typeof(e.preventDefault) !== "undefined") { e.preventDefault(); }
}

/**
 * Checks if a given element has a given CSS class defined or not.
 * @param DOMElement|String The element to check its classname.
 * @param String The classname to search for.
 */
function elementHasClassName(element, className) {   
    var obj = (element.className ? element : (typeof(element) === "string" ? $(element) : ""));
    if(!obj || !obj.className) { return false; }    
    var _names = element.className.split(/\s+/);
    for(x = 0; x < _names.length; x++) {
        if(_names[x] === className) { return true; }         
    }    
    return false;    
}

/**
 * Returns an array of nodes that match with a given CSS class name.
 * @param String. The class name to search for.
 * @param Boolean. True for a recursive search, false otherwise. Defaults to true.
 * @param DOMElement|String. The element to start the search at. Defaults to document.body.
 */   
function getElementsByClassName(className, recursive, startNode) {
    var _nodeBuilder = [];
    var _className   = (typeof(className) === "string" && className !== "" ? className : "");
    var _recursive   = (_recursive === false ? false : true); 
    var _startNode   = (startNode && startNode.nodeType === 1 ? startNode : document.body);    
    if(_className !== "") { buildNodes(_startNode); }
    
    // Return the array
    return _nodeBuilder;
    
    // function to recursively look up the nodes
    function buildNodes(node) {
        if(node.nodeType && node.nodeType === 1) {
            for(var child = node.firstChild; child !== null; child = child.nextSibling) {
                if(child.nodeType === 1) {
                    if(elementHasClassName(child, _className)) { _nodeBuilder.push(child); }
                    if(_recursive && child.childNodes.length > 0) { buildNodes(child); }
                }   
            }
        }
    }
}

/**
 * Returns an array of nodes that match a given attribute name.
 * @param String The attribute name to search for.
 * @param Boolean Not required. Set to true for a recursive lookup. Defaults to true.
 * @param DOMElement|String. Not required. The element to start. Defaults to document.body.
 */
function getElementsByAttribute(attr, recursive, startNode) {
    var _attr        = (typeof(attr) === "string" && attr !== "" ? attr : "");
    var _recursive   = (recursive === false ? false : true);
    var _startNode   = (startNode && startNode.nodeType === 1 ? startNode : document.body);
    var _nodeBuilder = [];
    
    if(_attr !== "") { buildNodes(_startNode); }    
    return _nodeBuilder;

    // function to retrieve nodes recursively    
    function buildNodes(node) {    
        if(node && node.nodeType === 1) {        
            for(var child = node.firstChild; child !== null; child = child.nextSibling) {            
                if(child.nodeType === 1 && child.getAttribute(_attr, 0) !== null && child.getAttribute(_attr, 0) != undefined) { _nodeBuilder.push(child); }                
                if(_recursive && child.childNodes.length > 0) { buildNodes(child); }                
            }
        }        
    }   
}

/**
 * Returns an array of nodes that match a given attribute name and attribute value.
 * @param String Name of the attribute to look for.
 * @param Mixed Attribute value to match.
 * @param Boolean Not required. Set to true to do a recursive lookup. Defaults to true.
 * @param DOMElement Not required. The element to start the search at. Defaults to document.body.
 */
function getElementsByAttrValue(attr, attrValue, recursive, startNode) {
    var _attr        = (typeof(attr) === "string" && attr !== "" ? attr : "");
    var _attrValue   = attrValue;
    var _recursive   = (recursive === false ? false : true);
    var _startNode   = (startNode && startNode.nodeType === 1 ? startNode : document.body);
    var _nodeBuilder = [];
    
    if(attr !== "") { buildNodes(_startNode); }    
    return _nodeBuilder;

    // function to retrieve nodes recursively    
    function buildNodes(node) {
        if(node && node.nodeType === 1) {
            for(var child = node.firstChild; child !== null; child = child.nextSibling) {
                if(child.nodeType === 1 && child.getAttribute(_attr, 0) === _attrValue) {
                    _nodeBuilder.push(child);
                }
                if(_recursive && child.childNodes.length > 0) {
                    buildNodes(child);
                }
            }
        }
    } 
}

/**
 * Converts a string containing JSON to a JSON object instance.
 * @param String Required. The string value containing the JSON to convert.
 */
function toJSON(jsonString) {	
	var fn = null;
	try {
		var fn = new Function("return " + jsonString)();
	}
	catch(e) { fn = null; }
	return fn;
}

/**
 * Checks if a given number is numeric or NaN (not a number).
 * @return boolean True if the given string is a number, false otherwise.
 * @param any The value to validate as an integer value.
 */
function isNumeric(num) {
	try {
		var nr = new Number(num);
	}
	catch(e) {
		return false;
	}
	return !isNaN(nr);
}

/**
 * Extracts all numbers from a string.
 * @return integer The numbers extracted from the given string.
 * @param string The string to extract numbers from.
 * @remarks This works for integers, do not attempt to use it for float values. Float values will become integers without conversion: 2.50 will become 250.
 */
function extractNumbers(str) {
	if(typeof(str) !== "string" || str.length == 0) {
		return NaN;
	}
	else {
		var nr = "";
		for(x = 0; x < str.length; x++) {
			if(!isNaN(str.substr(x, 1))) {
				nr += str.substr(x, 1);
			}
		}
		return new Number(nr);
	}
	return NaN;
}

/**
 * Checks if a given year is a leap year.
 * @return boolean True if the given year is a leap year, false otherwise.
 * @param integer The year to perform a leap year check on.
 */
function isLeapYear(theYear) {
	var result = false;
	if(isNaN(theYear)) { return false; }
	if(theYear % 4 == 0) { result = true; }
	if(theYear % 100 == 0) {
		if(theYear % 400 == 0) { result = true; }
	}	
	return result;
}

/**
 * Returns the number of days in a given month.
 * @return integer The number of days
 * @param integer The month to return a number of days of.
 * @param integer The year. This is used to check the number of days in a leap year for february.
 * @remarks This function checks for leap years if a year value is supplied.
 */
function nrOfDaysInMonth(theMonth, theYear) {
	var nr30 = "4,6,9,11";
	if(theMonth != 2 && nr30.search(theMonth.toString()) > -1) {
		return 30;
	}
	else if(theMonth == 2) {
		if(typeof(theYear) == "number") {
			if(isLeapYear(theYear)) {
				return 29;
			}
			else { return 28; }
		}
		else { return 28; }	
	}
	else { return 31; }
}

/**
 * Validates if the key pressed yields a valid character for use in a date value.
 */
function ValidateDate(evt) {
   var e = evt || event;
   var keyCode = e.keyCode || e.which;
   var typedChar = String.fromCharCode(keyCode);
   var allowedChars = '-1234567890';	
   return (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
}

/**
 * Validates if the key pressed yields a valid character for use in a time value.
 */
function ValidateTime(evt) {
   var e = evt || event;
   var keyCode = e.keyCode || e.which;
   var typedChar = String.fromCharCode(keyCode);
   var allowedChars = ':1234567890';	
   return (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
}

/**
 * Validates if the key pressed yields a valid character for use in a time value.
 */
function ValidateNumber(scale, bNonNegative, evt, allowCalculation) {
   var e = evt || event;
   var keyCode = e.keyCode || e.which;
   var typedChar = String.fromCharCode(keyCode);
   var allowedChars = '.1234567890';
   if(allowCalculation && allowCalculation === true) {
      allowedChars += '+/*%^#()'; // add, division, multiplication, modulo, power, square root.
   }
   if (scale > 0) allowedChars += ',';
   if (!bNonNegative || (allowCalculation && allowCalculation === true)) allowedChars += '-';
   var bValid = (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
   return bValid;
}

/**
 * Attempts to round a number from a NumberField control.
 * @param Event|null Key input event object.
 * @param String     DOMElement ID of the NumberField control to attempt rounding for.
 * @param Integer    Charcode for rounding. Use this only when no key input event is available.
 */
function roundNumberFieldVal(evt,id,keyVal) {
   var el = $(id);
   var val = el.value;
   var e = evt || event || null;
   var keyCode;
   if(e !== null && typeof(keyVal) == "undefined") {
      keyCode = e.keyCode || e.which;
   }
   else if(typeof(keyVal) !== "undefined") {
      keyCode = keyVal;
   }
   else return;
   
   var restoreComma = false;
   var tooltip = "";
   val = new String(val);
   if(val.indexOf(",") > -1) {
      val = val.replace(/,/g, ".");
      restoreComma = true;
   } 
   var tmpVal = new Number(val);      
  
   if(isNaN(tmpVal)) return;
   if(e.ctrlKey || typeof(keyVal) !== "undefined") {   
      var strVal = new String(val);
      switch(keyCode) {
         case 37:                        
            if(strVal.indexOf(".") > 0) {
               var tmpVals = strVal.split(".");
               var tmpDigits = "";
               var lastDigit = "";
               var tmpDec = tmpVals[1];
               var leadingZero = false;
               if(tmpVals[1].length > 2) {
                  if(tmpDec.substr(0,1) == "0") {
                     tmpDec = "1" + tmpDec;
                     leadingZero = true;
                  }
                  var max = tmpVals[1].length - 1;                  
                  while(tmpDec.length > (leadingZero ? 3 : 2)) {
                     lastDigit = tmpDec.substr(tmpDec.length - 1, 1);
                     tmpDigits = tmpDec.substring(0, tmpDec.indexOf(".") > -1  ? tmpDec.length - 2 : tmpDec.length - 1);                 
                     tmpDec = tmpDigits + "." + lastDigit;
                     if(lastDigit == "5") {                     
                        // Bankers' rounding:
                        var tie = tmpDigits.substr(tmpDigits.length-1,1);
                        tmpDec = (tie % 2 == 0 ? tmpDigits : new String(Math.round(tmpDec)));
                     }
                     else {
                        tmpDec = new String(Math.round(tmpDec));
                     }
                     
                  }
                  tmpDec = tmpDec.length == 3 ? tmpDec.substr(1,2) : tmpDec;
                  val = tmpVals[0] + "." + (tmpDec.length == 1 ? tmpDec + "0" : tmpDec);
               }
            }
            else if(strVal.length > 0) {
               val += ",00";
            }            
            break;
         case 38:
            val = Math.ceil(val);
            break;
         case 39:         
            val = Math.round(val);
            break;
         case 40:
            val = Math.floor(val);
            break;                        
      }
                  
      if(restoreComma) {
         val = new String(val);
         val = val.replace(/[.]/g, ",");         
      }
      el.value = val;
      el.title = strVal + "~" + val;
   }
}

/**
 * Attempts to make calculations, if any, in a number field control.
 * Requires FormValidation.js.
 */
function calculateField(e, id) {
   var fld = $(id);
   var val;
   if(fld) {      
      var restoreComma = false;			
	   val = fld.value;	   
	   if(formValidation.hasLower(val) || formValidation.hasUpper(val) || !formValidation.hasNumbers(val)) { 
	      return; 
	   }
	   	   
	   if(val.indexOf(",") > -1) {
	      val = val.replace(/,/g, ".");
	      restoreComma = true;
	   }
	   
	   // Square root
	   if(val.substr(0,1) == "#" && val.length > 1) {		   
		   val = "Math.sqrt(" + val.substring(1) + ")"					
	   }
	   
	   // Power
	   if(val.indexOf("^") > -1) {
		   		   val = val.replace("^", ",");
		   val = "Math.pow(" + val + ")";
	   }
	   
	   // Pct base amount (19-%119) 
	   if(val.indexOf("-%") > -1) {
	      val = val.replace("-%", "%");
	      var tmpVals = val.split("%");
	      val = "100*" + tmpVals[1] + "/(100+" + tmpVals[0] + ")";
	   }
	   
	   // VAT from inclusive amount (19+%119)   
	   if(val.indexOf("+%") > -1) {
	      val = val.replace("+%", "%");
	      var tmpVals = val.split("%");
	      val = tmpVals[1] + "-(100*" + tmpVals[1] + "/(100+" + tmpVals[0] + "))"; 
	   }

	   // Pct
	   if(val.indexOf("%") > -1 && val.indexOf("%%") == -1) {
	      var tmpVals = val.split("%");
	      val = "(" + tmpVals[0] + "*" + tmpVals[1] + ")/100";
	   }	   
	   
	   // Modulo
	   if(val.indexOf("%%") > -1) {
	      val = val.replace("%%", "%");
	   }

	   try {
		   // Other calculations
		   var calc = val;
		   var res = eval(val);
		   if(res == undefined) res = "";
		   if((!val || val.length == 0) || (res !== Infinity && !isNaN(res))) {
			   
			   var tmp = new String(res);
			   if(tmp.length > 1 && tmp.indexOf(".") == tmp.length - 2) {
			      tmp += "0";
			      res = tmp;
			   }
			   			   
			   if(restoreComma) {
			      tmp = tmp.replace(/[.]/g, ",");
			      res = tmp;
			   }
			   fld.value = res;
			   tooltip = res != calc ? calc + " = " + res : "";			  
			   formValidation.applyStatus(fld, 0, tooltip, "calculate");
			   roundNumberFieldVal(null, id, 37); // Round on 2 decimals						
		   }
		   else {
			   formValidation.applyStatus(fld, 3, "Geen getal of fout in formule", "calculate");					
		   }
	   }
	   catch(e) { formValidation.applyStatus(fld, 3, "Geen getal of fout in formule", "calculate"); }
   }
   else {
	   if(val.length > 0) {
		   formValidation.applyStatus(fld, 3, "Geen getal of fout in formule", "calculate");
	   }
   }
}

/**
 * Shorthand for document.getElementById();
 */
function $(id) {
   return document.getElementById(id);
}
function FindElement(id) { return $(id) }

function GetElementValue(id) {
   var el = $(id);
   var value;	
   if ( el != null ) value = el.value;
   return value;
}

function SetElementValue(id, value) {
   var el = $(id);
   if ( el != null ) el.value = value;
}

function GetObjectElementText(el) {
   if (el != null) {
      var displayValue = el.getAttribute("displayValue");
      if(displayValue) {
         return displayValue;
      }
      if (browserInfo.isIE()) {
         return el.innerText;
      }
      else {
         return el.textContent;
      }
   }
}

function GetElementText(id) {
   return GetObjectElementText($(id));
}

function SetObjectElementText(el, value) {
   if (el != null) {
      if ( browserInfo.isIE() ) {
         el.innerText = value;
      }
      else {
         if (el.tagName == 'INPUT') el.value = value;
         else el.textContent = value;
      }
   }
}

function SetElementText(id, value) {
   SetObjectElementText($(id), value);
}

/**
* Hides or unhides an HTML DOM element.
* @param string HTML DOM element ID.
* @param boolean True to show the element, false to hide the element. [optional]. Defaults to false. 
* @param string CSS display value to apply. [optional]. Defaults to 'block'.
* @return void
*/
function ShowElement(id, show, display) {
   var el = $(id);
   var disp = !display ? "block" : display;
	if (el != null) el.style.display = show === true ? disp : "none";
}

function ShowElement2(id, show) {
	var el = $(id);
	if ( el != null ) el.style.display = show ? '' : 'none';
}

function SubmitForm() {	
	try {
		document.forms[0].submit();
	}
	catch (ex) {
		window.alert(ex.description);
	}
}

function ValidateForm() {
	SetElementValue('DCValidation', 1);
	SubmitForm();
}

function FireEvent(el, eventName) {
    // On IE
    if (el.fireEvent) {
        el.fireEvent("on" + eventName);
    }
    // On Gecko based browsers
    else if (document.createEvent) {
        var evt = document.createEvent("HTMLEvents");
        if (evt.initEvent) {
            evt.initEvent(eventName, true, true);
        }
        if (el.dispatchEvent) {
            el.dispatchEvent(evt);
        }
    }
}

var msgConfirmDelete;
function SubmitForDelete() {
	if (msgConfirmDelete == null || msgConfirmDelete.length == 0)
		msgConfirmDelete = 'Weet u zeker dat u deze gegevens wilt verwijderen?';
	if (confirm(msgConfirmDelete)) {
		SetElementValue('DCAction', 2);
		SubmitForm();
	}
}

function BrowseData(id, returnFunction, returnFunctionParam, width, height) {
	return BrowseDataParam(id, null, null, returnFunction, returnFunctionParam, width, height);
}

function BrowseDataParam(id, clientParam, browseParam, returnFunction, returnFunctionParam, width, height) {
	var options;
	if (width == null) width = 700;
	options = 'dialogWidth:' + width.toString() + 'px';
	if (height == null) height = 400;
	options += ';dialogHeight:' + height.toString() + 'px';
	var url = 'DataBrowser.aspx?ID=' + escape(id)
	if (clientParam != null && clientParam.length > 0 && browseParam != null && browseParam.length > 0) {
		var paramNames = browseParam.split(',');
		var paramValues = clientParam.split(',');
		if (paramNames.length == paramValues.length) {
			for (var i = 0; i < paramNames.length; i++) {
				url += '&ParamName=' + paramNames[i] + '&ParamValue=' + escape(GetElementValue(paramValues[i]));
			}
		}
		else {
			url += '&ParamName=' + browseParam + '&ParamValue=' + escape(GetElementValue(clientParam));
		}
	}	
	
	var value = showModalDialog(url, null, options);
	if (typeof(value) != 'undefined') {
		if ( returnFunction != null ) {
			if ( returnFunctionParam != null ) {
				returnFunction(returnFunctionParam, value);
			}
			else {
				returnFunction(value);
			}
		}
	}
	return value;
}

function doRowColor(className) {
   var cls = className.toLowerCase().trim();
   if (cls.length == 0 || cls == "even" || cls == "uneven" || cls.indexOf("unread") > 0 || cls.indexOf("read") > 0 || cls.indexOf("pastduedate") > 0 || cls.indexOf("negativebalance") > 0 || cls.indexOf("incorrectbalance") > 0) {
	   return true;
   }
   return false;   
}

function BrowseDataOnMouseOver(evt) {
    var e = typeof(event) !== "undefined" ? event.srcElement : evt.target;
	 if (e != null && e.tagName == "TD") {
		var p = e.parentNode;
		if (p != null && p.tagName == "TR") {
			var className = p.className;
			if ((className.indexOf("Even") == 0 || className.indexOf("Uneven") == 0) && className.indexOf(" ") == -1) {
				e.parentNode.className = "Selected";
			}
		}
	}
}

function BrowseDataOnMouseOut(evt) {
   var e = typeof(event) !== "undefined" ? event.srcElement : evt.target;
	if (e != null && e.tagName == "TD") {
		var p = e.parentNode;
		if (p != null && p.tagName == "TR") {
			if (p.className == "Selected") {
				p.className = ((p.rowIndex % 2) != 0) ? "Uneven" : "Even";
			}
		}
	}
}

function BrowseDataOnClick(event) {
	var e = event.target || window.event.srcElement;
	if (e.tagName == "TD") BrowseDataSelect(e.parentNode);
}

function BrowseDataSelect(row) {
	if (row != null && row.tagName == "TR") {
		if(typeof(closePopupFrame) === "undefined" || closePopupFrame === false) {
			window.parent.returnValue = new Array(row.id, row.title);
			window.parent.close();
		}
		else {
			parent.popupFrame.result([row.id, row.title]);
			parent.popupFrame.close();
		}
	}
}

function BrowseDataOnKeyPress(event) {
}

function SetBrowseResult(id, value) {
	if(value !== null) {
		SetElementValue(id, value[0]);
		SetElementValue(id + '_RefValue', value[1]);
	}
}

function AddContactList(id, value) {
   if (!value || value.length < 2) { return; } 
	var separator = id.substr(0, 1);
	id = id.substr(1, id.length - 1);
	var inputValue = GetElementValue(id);
	var bInputValue = inputValue != null && inputValue.length > 0;
	if (bInputValue) inputValue += '; ';
	inputValue += value[1];
	SetElementValue(id, inputValue);
	var idsName = id + '_ids';
	var ids = $(idsName);
	if (ids != null) {
		var idValue = GetElementValue(idsName);
		var bIdValue = idValue != null && idValue.length > 0;
		if (!bInputValue || bIdValue) {
			if (bIdValue) idValue += ',';
			idValue += value[0];
			SetElementValue(idsName, idValue);		
		}
	}
}

function AddLabelField(id, value) {
	var inputValue = GetElementValue(id);
	var bInputValue = inputValue != null && inputValue.length > 0;
	if (bInputValue) inputValue += ' ';
	inputValue += value[1];
	SetElementValue(id, inputValue);
}

function WriteFlash(width, height, file, link) {
	if ( browserInfo.isIE() ) {
		document.write('<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="');
		document.write(width);
		document.write('" height="');
		document.write(height);
		document.writeln('" viewastext>');
		document.write('<param name="movie" value="');
		document.write(file);
		document.writeln('">');
		if (link != null && link.length > 0) {
			document.write('<param name="base" value="');
			document.write(link);
			document.writeln('">');
		}
		document.writeln('</object>');
	}
	else {
		document.write('<embed src="');
		document.write(file);
		document.write('" base="');
		document.write(link);
		document.write('" width="');
		document.write(width)
		document.write('" height="');
		document.write(height);
		document.writeln('"	type="application/x-shockwave-flash"></embed>');	
	}
}

function WriteTiffViewer(width, height, url) {
	if ( browserInfo.isIE() ) {
		document.write('<object classid="CLSID:106E49CF-797A-11D2-81A2-00E02C015623"');
		document.write('codebase="alternatiffx-1_8_2.cab#version=1,8,2,1"');
		document.write(' width="');
		document.write(width);
		document.write('" height="');
		document.write(height);
		document.writeln('" viewastext>');		
		document.write('<param name="src" value="');
		document.write(url);
		document.writeln('">');		
		document.writeln('</object>');
	}
	else {
		document.write('<embed src="');
		document.write(url);
		document.write('" width="');
		document.write(width)
		document.write('" height="');
		document.write(height);
		document.writeln('" type="image/tiff"></embed>');	
	}
}

function WritePDFViewer(width, height, url) {
	if ( browserInfo.isIE() ) {
		document.write('<object classid="CLSID:CA8A9780-280D-11CF-A24D-444553540000"');
		document.write(' type="application/pdf"');
		document.write(' width="');
		document.write(width);
		document.write('" height="');
		document.write(height);
		document.writeln('" viewastext>');		
		document.write('<param name="src" value="');
		document.write(url);
		document.writeln('">');		
		document.writeln('</object>');
	}
	else {
		document.write('<embed src="');
		document.write(url);
		document.write('" width="');
		document.write(width)
		document.write('" height="');
		document.write(height);
		document.writeln('" type="application/pdf"></embed>');	
	}
}

function GetXmlHttpRequestObject() {
	var xmlhttp = null;
	if(browserInfo.isIE()) {
		try {
			xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
		}
		catch(err) {
			try {
				xmlhttp = new ActiveXObject("MSXML.XMLHTTP");
			}
			catch(err2) { }
		}
	}
	else {
		if(typeof(XMLHttpRequest) !== "undefined") {
			xmlhttp = new XMLHttpRequest();
		}	
	}
	return xmlhttp;
}

function DoAsyncXmlRequest(xmlhttp, target, callbackFunction) {
	xmlhttp.open("GET", target);
	if (typeof(callbackFunction) == "function") { 
		xmlhttp.onreadystatechange = callbackFunction; 
	}
	xmlhttp.send(null);
}

function GetAbsoluteElementPosition(el) {
	for(var lx=0, ly=0; el != null; el = el.offsetParent) {
		lx += el.offsetLeft;
		ly += el.offsetTop;
		if(browserInfo.isIE()) {
			lx += el.clientLeft;
			ly += el.clientTop;
		}
		if (el.tagName.toLowerCase() == 'div') {
			if (el.scrollLeft > 0) lx -= el.scrollLeft;
			if (el.scrollTop > 0) ly -= el.scrollTop;
		}
	}
	return {x:lx, y:ly};
}

function getPageSize(){
	var xScroll, yScroll;
	if (window.innerHeight && window.scrollMaxY) {
             xScroll = document.body.scrollWidth;
             yScroll = window.innerHeight + window.scrollMaxY;
     } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
             xScroll = document.body.scrollWidth;
             yScroll = document.body.scrollHeight;
     } else if (document.documentElement && document.documentElement.scrollHeight > document.documentElement.offsetHeight){ // Explorer 6 strict mode
             xScroll = document.documentElement.scrollWidth;
             yScroll = document.documentElement.scrollHeight;
     } else { // Explorer Mac...would also work in Mozilla and Safari
             xScroll = document.body.offsetWidth;
             yScroll = document.body.offsetHeight;
     }
          var windowWidth, windowHeight;
     if (self.innerHeight) { // all except Explorer
             windowWidth = self.innerWidth;
             windowHeight = self.innerHeight;
     } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
             windowWidth = document.documentElement.clientWidth;
             windowHeight = document.documentElement.clientHeight;
     } else if (document.body) { // other Explorers
             windowWidth = document.body.clientWidth;
             windowHeight = document.body.clientHeight;
     }
          // for small pages with total height less then height of the viewport
     if(yScroll < windowHeight){
             pageHeight = windowHeight;
     } else {
             pageHeight = yScroll;
     }
          // for small pages with total width less then width of the viewport
     if(xScroll < windowWidth){
             pageWidth = windowWidth;
     } else {
             pageWidth = xScroll;
     }
    return [pageWidth,pageHeight,windowWidth,windowHeight];
}

function HandleNameSearchResult() {
	if (nameSearchTarget == null || xmlhttpNameSearch == null || xmlhttpNameSearch.readyState != 4) return;
	var response = xmlhttpNameSearch.responseText;		
	if (response == null || response.length == 0) DelayedHideNameSearch();
	
	var style;
	if (divNameSearch == null) {
		divNameSearch = document.createElement("div")
		document.body.appendChild(divNameSearch);
		style = divNameSearch.style;
		style.position = 'absolute';	
		style.height = "125px";	
		style.borderColor = '#808080';
		style.borderStyle = 'solid';
		style.backgroundColor = '#FDFDFD';
		style.borderWidth = '1px';
		style.overflow = 'auto';
	}
	else { style = divNameSearch.style; }	
	divNameSearch.innerHTML = response;
	
	// Make sure the anchors fire the onchange event for the text inputfield.
	var anchors = divNameSearch.getElementsByTagName("A");
	for(var x = 0; x < anchors.length; x++) {
	   try {
	      addEvent(anchors[x], "click", function() { FireEvent(nameSearchTarget, "change") });
	   }
	   catch(e) { alert(e.message); }
	}

	var pos = GetAbsoluteElementPosition(nameSearchTarget);
	var sizeOfDocument = getPageSize();
	style.left = pos.x - 3;
	
	if (parseInt(pos.y) + parseInt(style.height) > parseInt(sizeOfDocument[3])) {
		style.top = pos.y  - 2 - parseInt(style.height);
	} else {
		style.top = pos.y + nameSearchTarget.offsetHeight - 2;
	}
	
	style.width = nameSearchTarget.offsetWidth + 20;
	if(extractNumbers(style.width) < 225) {
		style.width = "225px";
	}
	style.visibility = 'visible';
	style.display = 'inline';
	style.zIndex = 1;
	
	if (frameNameSearch == null) {
		frameNameSearch = document.createElement("iframe")
		frameNameSearch.src = "blank.htm";
		frameNameSearch.border = 0;			
		document.body.appendChild(frameNameSearch);
		nameSearchTarget.focus();
	}
	var fstyle = frameNameSearch.style;
	fstyle.visibility = 'visible';
	fstyle.position = 'absolute';
	fstyle.left = style.left;
	fstyle.top = style.top;
	fstyle.height = style.height;
	fstyle.width = style.width;
	fstyle.display = 'inline';	
	fstyle.zindex = -1;			
}

var bDontHideNameSearch = false;
function HideNameSearch() {
	if (bDontHideNameSearch) return;
	if (divNameSearch != null ) {
		divNameSearch.style.visibility = 'hidden';
	}
	if (frameNameSearch != null ) {
		frameNameSearch.style.visibility = 'hidden';
	}	
}

function DelayedHideNameSearch() {
	setTimeout('HideNameSearch()', 200);
}

function SearchElementChanged() {
	if (nameSearchTarget == null) return;
	FireEvent(nameSearchTarget, "change");
}

var nameSearchTimeoutID;
function DoNameSearch(e, id, target) {
	var key = e.keyCode || e.which;
	if (key < 48 && key != 8) return;
	if (nameSearchTimeoutID != null) clearTimeout(nameSearchTimeoutID);
	nameSearchTimeoutID = setTimeout('DoDelayedNameSearch(\'' + id + '\',\'' + target + '\')', 350);
}

function DoDelayedNameSearch(id, target) {
	nameSearchTimeoutID = null;
	nameSearchTarget = $(id);
	
	var value;
	if (nameSearchTarget != null) { value = nameSearchTarget.value; }
	if (value == null || value.length == 0) {
		DelayedHideNameSearch();
		return;
	}
	
	if (xmlhttpNameSearch == null) xmlhttpNameSearch = GetXmlHttpRequestObject();
	else xmlhttpNameSearch.abort();
	
	target = target + ((target.indexOf('?') < 0) ? '?' : '&');
	target = target + 'NameSearch=' + encodeURIComponent(value);
	DoAsyncXmlRequest(xmlhttpNameSearch, target, HandleNameSearchResult)
}

function NameSearchDown(event) {
	if (divNameSearch != null && divNameSearch.style.visibility == 'visible') {
		var firstChild = divNameSearch.children[0];
		if (firstChild != null) {
			bDontHideNameSearch = true;
			firstChild.focus();
		}
		event.returnValue = false;
	}
}

function NameSearchKeyDown(e) {
	if (divNameSearch == null || divNameSearch.style.visibility != 'visible') return;
	var key = e.keyCode;
	if (key === 40 || key === 38) {
		e.returnValue = false;	 
		var current = document.activeElement;
		if (current != null) {
			var el;
			if (key == 40) el = current.nextSibling;
			else el = current.previousSibling;
			if (el != null && el.tagName == 'A') {
				el.focus();
			}
		}
	}
	else if (key === 27) {
		bDontHideNameSearch = false;
		HideNameSearch();
		nameSearchTarget.focus();
	}
}

function SelectNameSearchElement(el) {
	if (el == null || nameSearchTarget == null) return;
	SetObjectElementText(nameSearchTarget, GetObjectElementText(el));
	bDontHideNameSearch = false;
	HideNameSearch();
	nameSearchTarget.focus();
	if (browserInfo.isIE()) {
		var l = nameSearchTarget.value.length;
		if (l > 0) {
			var tr = nameSearchTarget.createTextRange();
			tr.moveStart('character', l);
			tr.select();
			tr.collapse(false);
		}
	}
}

function dataListRowOver(el, e) {
   if(el.className.length == 0 || el.className == 'Even' || el.className == 'Uneven') el.className+=' datalistRowHover';
}

function dataListRowOut(el, e) {
   el.className = el.className.replace(' datalistRowHover', '');
}

function ftbInsertImage(ftb, reserved) {
	var value = BrowseData('FTBInsertImage.aspx', null, null, 750, 400);
	if (typeof(value) == 'undefined') return;	
	var tag = '<img alt="' + value[2] + '" src="';
	if (value[0] == 1) {
		tag += 'Picture.aspx?Type=2&ID=' + value[1];
		if (value[3] != null && value[3].length > 0) tag += '&MaxHeight=' + value[3];
		if (value[4] != null && value[4].length > 0) tag += '&MaxWidth=' + value[4];
		tag += '"';
	} 
	else {
		tag += value[1] + '"';
		if (value[3] != null && value[3].length > 0) tag += ' height="' + value[3] + '"';
		if (value[4] != null && value[4].length > 0) tag += ' width="' + value[4] + '"';
	}
	tag += '>';
	ftb.InsertHtml(tag);
}

function ftbInsertLink(ftb, reserved) {
	var value = BrowseData('FTBInsertLink.aspx', null, null, 750, 400);
	if (typeof(value) == 'undefined') return;	
	var tag = '<a href="';
	var url;
	if (value[0] == 1) {
		url = 'Document.aspx?ID=' + value[1];
		var accessID =  value[3];
		if (accessID != null && accessID.length > 0) url += '&AccessID=' + value[3];
		tag += url + '"';
		tag += ' target="_blank"';
		tag += '>';
	} 
	else {
		url = value[1];
		tag += url + '" target="_blank">';
	}
	var desc = value[2];
	if (desc == null || desc.length == 0) desc = url;
	tag += desc;
	tag += '</a>'
	ftb.InsertHtml(tag);
}

function ToggleDisplay(id) {
	var e = $(id);
	if (e != null) {
		if (e.style.display == 'none') {
			e.style.display = 'inline';
		}
		else {
			e.style.display = 'none';
		}	
	}
}

function SetLabelListMode(mode) {
	SetElementValue('LabelListMode', mode);
	var lm;
	for (var i = 0; i <= 2; i++) {
		lm = $('LabelListMode_' + i);
		if (lm != null) lm.className = i == mode ? 'Selected' : '';
	}
	var row,parentid,img,show;
	var ll = $('LabelList');
	for (var i = 1; i < ll.rows.length; i++) {
		row = ll.rows[i];
		show = mode == row.mode;
		if (show) {
			parentid = row.getAttribute('parentid');
			if (parentid != null && parentid.length > 0) {
				img = $('img' + parentid);
				show = img.src.substr(img.src.lastIndexOf('/') + 1) == 'fw1050-10.gif';
			}
		}
		row.style.display = (show ? (browserInfo.isIE() ? 'block' : 'table-row') : 'none');
	}
}

var fnExpandLabelList = null;
function ShowLabelList(mode) {
	var pos = GetAbsoluteElementPosition($('LabelListTabs'));
	var ll = $('divLabelList');
	if (ll == null) {
		return;
	}
	if (ll.style.display == 'none') {
		ll.style.top = pos.y - 1;
		ll.style.width = 185;
		ll.style.left = pos.x - 185;
		ll.style.display = 'block';
		if (fnExpandLabelList != null) {
			fnExpandLabelList(true);
		}
		SetLabelListMode(mode);
		$('LabelListTab' + mode).className = 'LabelListTabActive';
	}
	else {
		var llm = $('LabelListMode');
		if (llm == null || mode == -1) {
			ll.style.display = 'none';
			if (fnExpandLabelList != null) fnExpandLabelList(false);
			for (i = 0; i <= 2; i++) {
				if($('LabelListTab' + i) != null)
				{
				$('LabelListTab' + i).className = 'LabelListTab';
			}
		}
		}
		else {
			var curMode = GetElementValue('LabelListMode');
			if (curMode == mode)	{
				ll.style.display = 'none';
				if (fnExpandLabelList != null) fnExpandLabelList(false);
				$('LabelListTab' + mode).className = 'LabelListTab';
			}
			else {
				SetLabelListMode(mode);
				var i, tab;
				for (i = 0; i <= 3; i++) {
					tab = $('LabelListTab' + i);
					if (tab != null) {
						if (i == mode)	tab.className = 'LabelListTabActive';
						else tab.className = 'LabelListTab';
					}
				}			
			}
		}
	}
}

function ToggleSection(imgname, secname) {
	var sec = $(secname); 
	if (sec != null) {
		if ( sec.style.display == 'none' ) {
			sec.style.display = 'inline';
			$(imgname).src = 'images/collapse-16.gif';
		}
		else {
			sec.style.display = 'none';
			$(imgname).src = 'images/expand-16.gif';
		}
	}
}
	
function FWInsertAtCaret(ctl, text) {
	if (ctl.createTextRange && ctl.caretPos){
		var caretPos = ctl.caretPos;
		caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == '' ? text + ' ' : text;
	}
	else {
		ctl.focus() ;
		if (ctl.value.length > 0) { ctl.value = ctl.value + " " + text ; } else {ctl.value = text ;}
	}
}

function FWStoreCaret (ctl) {
	if (ctl.createTextRange) { ctl.caretPos = document.selection.createRange().duplicate();}
}

function FWPad2 (i) {
	var res = i.toString();
	if (i < 10) res = '0' + res;
	return res;
}

function GetFrameWindow(frame) {
	if (browserInfo.isIE()) {
		return document.frames[frame.name];
	}
	else {
		if(frame.contentWindow) {
			return frame.contentWindow;
		} else { return frame; }
	}
}

function FWGetFrameLocation(frame) {
	var loc = GetFrameWindow(frame).location.href;
	var iStart = loc.lastIndexOf('/');
	var iEnd = loc.indexOf('?');
	if (iEnd >= 0) {
		var params = loc.substring(iEnd + 1).split('&');
		loc = loc.substring(iStart + 1, iEnd);
	}
	else loc = loc.substring(iStart + 1);
	return {filename:loc, queryparams:params}
}

function FWMatchUrl(loc, filename, params) {
	var bMatch = loc.filename.toLowerCase() == filename.toLowerCase();
	if (bMatch && params != null) {
		var queryparams = loc.queryparams;
		if (queryparams != null) {
			params = params.split('&');
			var bParamMatch;
			for (var i = 0; i < params.length; i++) {
				bParamMatch = false;
				for (var j = 0; j < queryparams.length; j++) {
					if (queryparams[j].toLowerCase() == params[i].toLowerCase()) {
						bParamMatch = true;
						break;
					}
				}
				if (!bParamMatch) {
					bMatch = false;
					break;
				}
			}
		}
	}
	return bMatch;
}

function disableNode(parentName) {
	var elements = new Array('table', 'tr', 'td', 'select', 'input');
	var element,children,parent,i,j;
	parent = $(parentName);
	if (parent != null) {
		parent.disabled = true;
		for (i = 0; i < elements.length; i++) {
			element = elements[i];
			children = parent.getElementsByTagName(element);
			if (children != null) {
				for (j = 0; j < children.length; j++) {
					children[j].disabled = true;
				}
			}
		}
	}
}

/**
 * Determines when the focus needs to shift to another input field of the same type.
 */
function clieOpNextField(nextFieldID, text, maxLen, doSelect) {
	var _max = (typeof(maxLen) === "number" ? maxLen : 4);
	if(text && text.length === _max) {
		var field = $(nextFieldID);
		if(typeof(doSelect) === "undefined" || doSelect === true) {
		   field.select();
		}
		field.focus();
	}
}

/**
 * Clears all default text input captions to prevent them
 * from being submitted as real values.
 */
function clearTICaptions() {
	// Clear text input captions
	var els = document.forms[0].getElementsByTagName("INPUT");
	for(x = 0; x < els.length; x++) {	
	   if(els[x].type == "text") {
	      var txt = els[x].getAttribute("tiText");	      
	      if(txt && !manageTICaption(els[x], 2)) {         
	         els[x].value = "";
	      }
	   }
	}
}

/**
 * Manages the state of an inputbox which has text input caption enabled, like search boxes.
 * @param DOMElement The INPUT element to apply the state change to
 * @param Integer The state action to take.
 */
function manageTICaption(el, action) {
   var tiText = el.getAttribute("tiText");
   switch(action) {
      case 0: // clear
         if(el.value == tiText || el.value == "") {
            el.value = "";
            el.className = el.getAttribute("defaultCss");
         }
         break;
      case 1: // restore
         if(el.value.length === 0) {
            el.value = el.getAttribute("tiText");
            var css = el.getAttribute("defaultCss");
            el.className = (css.length > 0 ? css + " " + " tiCaption" : "tiCaption");
         }
         break;
      case 2: // determine prevention of posting of text input caption
         if(el.value == el.tiText && el.className !== el.getAttribute("defaultCss")) {
            return false;
         }
         else return true;
   }
}

// ---------------------------------------
// Flash Player Version Detection - Rev 1.6
// Detect Client Browser type
// Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved.
function ControlVersion() {
   var version,axo,e;
   // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry
   try {
      // version will be set for 7.X or greater players
      axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
      version = axo.GetVariable("$version");
   } catch (e) { }

   if (!version) {
      try {
         // version will be set for 6.X players only
         axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");

         // installed player is some revision of 6.0
         // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,
         // so we have to be careful. 

         // default to the first public version
         version = "WIN 6,0,21,0";

         // throws if AllowScripAccess does not exist (introduced in 6.0r47)		
         axo.AllowScriptAccess = "always";

         // safe to call for 6.0r47 or greater
         version = axo.GetVariable("$version");

      } catch (e) { }
   }

   if (!version) {
      try {
         // version will be set for 4.X or 5.X player
         axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
         version = axo.GetVariable("$version");
      } catch (e) { }
   }

   if (!version) {
      try {
         // version will be set for 3.X player
         axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
         version = "WIN 3,0,18,0";
      } catch (e) { }
   }

   if (!version) {
      try {
         // version will be set for 2.X player
         axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
         version = "WIN 2,0,0,11";
      } catch (e) { version = -1; }
   }
   return version;
}

// JavaScript helper required to detect Flash Player PlugIn version information
function GetSwfVer() {
   // NS/Opera version >= 3 check for Flash plugin in plugin array
   var flashVer = null;
   if (navigator.plugins != null && navigator.plugins.length > 0) {
      if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
         var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
         var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
         var descArray = flashDescription.split(" ");
         var tempArrayMajor = descArray[2].split(".");
         var versionMajor = tempArrayMajor[0];
         var versionMinor = tempArrayMajor[1];
         var versionRevision = descArray[3];
         if (versionRevision == "") {
            versionRevision = descArray[4];
         }
         if (versionRevision[0] == "d") {
            versionRevision = versionRevision.substring(1);
         } else if (versionRevision[0] == "r") {
            versionRevision = versionRevision.substring(1);
            if (versionRevision.indexOf("d") > 0) {
               versionRevision = versionRevision.substring(0, versionRevision.indexOf("d"));
            }
         }
         flashVer = "WIN " + versionMajor + "," + versionMinor + "," + versionRevision;
      }
   }
   else if (browserInfo.isIE() && !browserInfo.isOpera()) {
      flashVer = ControlVersion();
   }
   return flashVer;
}
// --- End of Adobe Flash Player detection ---