// UTF8 URL decode

// This function returns the decimal value of two hexadecimal digits.
// Input is a percent sign followed by two hexadecimal digits. If the input
// string is shorter than three characters, the percent sign is missing or if
// not a hexadecimal numeral is used, then the decimal value 256 is returned:
function UTF8URLDecodeGetDec(hexencoded) {
  if (hexencoded.length == 3) {
    if (hexencoded.charAt(0) == "%") {
      if (hexchars.indexOf(hexencoded.charAt(1)) != -1 && hexchars.indexOf(hexencoded.charAt(2)) != -1) {
        return parseInt(hexencoded.substr(1,2),16);
      }
    }
  }
  return 256;
}

var unreserved = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~";
var reserved = "!*'();:@&=+$,/?%#[]";
var allowed = unreserved + reserved;
var hexchars = "0123456789ABCDEFabcdef";

function UTF8URLDecode(encoded) {
  // Some variables:
  var decoded = "";
  // Remember characters that are not allowed in a URL:
  var notallowed = "";
  // Remember illegal percent encoding:
  var illegalencoding = "";

  // ---------------- If UTF-8 character decoding was chosen: ----------------
  {
    // UTF-8 bytes from left to right:
    var byte1, byte2, byte3, byte4 = 0;

    var i = 0;
    while (i < encoded.length) {
      var ch = encoded.charAt(i);
      // Check for percent-encoded string:
      if (ch == "%") {

        // Check for legal percent-encoding of first byte:
        if (UTF8URLDecodeGetDec(encoded.substr(i,3)) < 255) {

          // Get the decimal values of all (potential) UTF-bytes:
          byte1 = UTF8URLDecodeGetDec(encoded.substr(i,3));
          byte2 = UTF8URLDecodeGetDec(encoded.substr(i+3,3));
          byte3 = UTF8URLDecodeGetDec(encoded.substr(i+6,3));
          byte4 = UTF8URLDecodeGetDec(encoded.substr(i+9,3));

          // Check for one byte UTF-8 character encoding:
          if (byte1 < 128) {
            decoded = decoded + String.fromCharCode(byte1);
            i = i + 3;
          }

          // Check for illegal one byte UTF-8 character encoding:
          if (byte1 > 127 && byte1 < 192) {
            decoded = decoded + encoded.substr(i,3);
            illegalencoding = illegalencoding + encoded.substr(i,3) + " ";
            i = i + 3;
          }

          // Check for two byte UTF-8 character encoding:
          if (byte1 > 191 && byte1 < 224) {
            if (byte2 > 127 && byte2 < 192) {
              decoded = decoded + String.fromCharCode(((byte1 & 0x1F) << 6) | (byte2 & 0x3F));
            } else {
              decoded = decoded + encoded.substr(i,6);
              illegalencoding = illegalencoding + encoded.substr(i,6) + " ";
            }
            i = i + 6;
          }

          // Check for three byte UTF-8 character encoding:
          if (byte1 > 223 && byte1 < 240) {
            if (byte2 > 127 && byte2 < 192) {
              if (byte3 > 127 && byte3 < 192) {
                decoded = decoded + String.fromCharCode(((byte1 & 0xF) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F));
              } else {
                decoded = decoded + encoded.substr(i,9);
                illegalencoding = illegalencoding + encoded.substr(i,9) + " ";
              }
            } else {
              decoded = decoded + encoded.substr(i,9);
              illegalencoding = illegalencoding + encoded.substr(i,9) + " ";
            }
            i = i + 9;
          }

          // Check for four byte UTF-8 character encoding:
          if (byte1 > 239) {
            if (byte2 > 127 && byte2 < 192) {
              if (byte3 > 127 && byte3 < 192) {
                if (byte4 > 127 && byte4 < 192) {
                  decoded = decoded + String.fromCharCode(((byte1 & 0x7) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) << 6) | (byte4 & 0x3F));
                } else {
                  decoded = decoded + encoded.substr(i,12);
                  illegalencoding = illegalencoding + encoded.substr(i,12) + " ";
                }
              } else {
                decoded = decoded + encoded.substr(i,12);
                illegalencoding = illegalencoding + encoded.substr(i,12) + " ";
              }
            } else {
              decoded = decoded + encoded.substr(i,12);
              illegalencoding = illegalencoding + encoded.substr(i,12) + " ";
            }
            i = i + 12;
          }

        } else {  // the first byte is not legally percent-encoded
          decoded = decoded + encoded.substr(i,3);
          illegalencoding = illegalencoding + encoded.substr(i,3) + " ";
          i = i + 3;
        }

      } else {  // the string is not percent encoded
        // Check if character is an allowed character:
        if (allowed.indexOf(ch) == -1) notallowed = notallowed + ch + " ";
        decoded = decoded + ch;
        i++;
      }
    }  // end of while ...

  }
  return decoded;
}

// busy functions - Peter Breitling

function uiFindElementPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	return [ curleft, curtop ];
}

function busyStart(parentElement) {
	if (typeof window.busyDiv == 'undefined' || window.busyDiv == null) {
		window.busyDiv = document.createElement("DIV");
		window.busyDiv.className = "renderbusystyle";
		window.busyDiv.style.zIndex = "20000";
		window.busyDiv.style.position = "fixed";
		window.busyDiv.style.left = "0px";
		window.busyDiv.style.top = "0px";
		window.busyDiv.style.width = "100%";
		window.busyDiv.style.height = "100%";
		window.busyDiv.style.visibility = "inherit";
//		window.busyDiv.innerHTML = '<div class="renderbusystyle"></div>';
//		window.busyDiv.innerHTML = 'Hello World!';
	}
//	if (navigator.platform.indexOf("iPhone") >= 0)
//	{
//	    var left,top;
//	    if (window.pageYOffset) // all except Explorer
//	    {
//	            left = window.pageXOffset;
//	            top = window.pageYOffset;
//	    }
//	    else if (document.body) // all other Explorers
//	    {
//	            left = document.body.scrollLeft;
//	            top = document.body.scrollTop;
//	    }
//		window.busyDiv.style.position = "absolute";
//		window.busyDiv.style.left = left+"px";
//		window.busyDiv.style.top = top+"px";
//	}
	//document.body.appendChild(window.busyDiv);
}

function busyStop() {
	if (typeof window.busyDiv != 'undefined' && window.busyDiv != null) {
		//document.body.removeChild(window.busyDiv);
		window.busyDiv = null;
	}
}

function checkBusy() {
	if (typeof document.readyState != 'undefined') {
		if (document.readyState == 'complete')
			busyStop();
		else
			setTimeout('checkBusy()', 500);
		return;
	} else {
		if (typeof document.getElementsByTagName != 'undefined'
				&& (document.getElementsByTagName('body')[0] != null || document.body != null))
			busyStop();
		else
			setTimeout('checkBusy()', 500);
		return;
	}
}

// busy functions end

// focus functions - Peter Breitling

function metastoresSetFocus()
{
	// handle focus hint
	
	if (typeof window.metastoresFocusedElementId!='undefined' && window.metastoresFocusedElementId!=null)
	{
		var element=document.getElementById(window.metastoresFocusedElementId);
		if (element) 
		{
			element.focus();
			return;
		}
	}
	
	// handle default focus hint
	
	if (typeof window.metastoresDefaultFocusedElementId!='undefined' && window.metastoresDefaultFocusedElementId!=null)
	{
		var element=document.getElementById(window.metastoresDefaultFocusedElementId); 
		if (element) 
		{
			element.focus();
			return;
		}
	}
}

// focus functions end

//metastores ui fragment controller - Peter Breitling

function metastoresEncodeURIComponent(component)
{
	if (typeof encodeURIComponent == 'undefined')
		return escape(component);
	else
		return encodeURIComponent(component);
}
function metastoresGetWindowId()
{
	if (typeof window.fragmentRequestClientId=='undefined')
	{
		window.fragmentRequestClientId=Math.random();
	}
	return window.fragmentRequestClientId;
}

function metastoresFragmentListen()
{
	// instanciate new listener if not already exists
	if (typeof window['metastoresFragmentListenConnector']=='undefined')
	{
		window['metastoresFragmentListenConnector']=new MetastoresFragmentConnector(Math.random(), true);
		var url=window.document.forms.mainform.action+'?metastores-ui-listen=true&window='+metastoresGetWindowId()+'&nocache='+Math.random();
		window['metastoresFragmentListenConnector'].send(url, "");
		return;
	}
	
	// check if ready and start listener
	if (window['metastoresFragmentListenConnector'].connector.readyState == 4)
	{
		window['metastoresFragmentListenConnector']=new MetastoresFragmentConnector(Math.random(), true);
		var url=window.document.forms.mainform.action+'?metastores-ui-listen=true&window='+metastoresGetWindowId()+'&nocache='+Math.random();
		window['metastoresFragmentListenConnector'].send(url, "");
	}
}

function metastoresFragmentRequest()
{
	// instanciate new request if not already exists
	if (typeof window['metastoresFragmentRequestConnector']=='undefined' || window['metastoresFragmentRequestConnector'].connector.readyState == 4)
	{
		if (typeof metastoresUnsetPlaceholders!='undefined') metastoresUnsetPlaceholders(); 
		window['metastoresFragmentRequestConnector']=new MetastoresFragmentConnector(Math.random(), false);
		var params='metastores-ui-fragment=true&window='+metastoresGetWindowId()+'&nocache='+Math.random()+window['metastoresFragmentRequestConnector'].inputElementsToUrlParameters(document.getElementById('mainform'));
		window['metastoresFragmentRequestConnector'].send(window.document.forms.mainform.action, params);
		if (typeof busyStart!='undefined') busyStart(); 
		return;
	}
	
	// check if ready and start listener
//	if (window['metastoresFragmentRequestConnector'].connector.readyState == 4)
//	{
//		window['metastoresFragmentRequestConnector']=new MetastoresFragmentConnector(Math.random(), false);
//		var url=window.document.forms.mainform.action+'?metastores-ui-fragment=true&window='+metastoresGetWindowId()+'&nocache='+Math.random()+window['metastoresFragmentRequestConnector'].inputElementsToUrlParameters(document.getElementById('mainform'));
//		window['metastoresFragmentRequestConnector'].send(url);
//	}
}

function MetastoresFragmentConnector(id, listen)
{
	// save id

	this.id=id;

	// save listen property

	this.listen=listen;

	// open connector

	{
	if (window.XMLHttpRequest)
	    {
	        this.connector = new XMLHttpRequest();
	    }
	    else if (window.ActiveXObject)
	    {
	        try
	        {
	            this.connector = new ActiveXObject("Msxml2.XMLHTTP");
	        }
	        catch (e1)
	        {
	            try
	            {
	                this.connector = new ActiveXObject("Microsoft.XMLHTTP");
	            }
	            catch (e2)
	            {
	            	alert('Incompatible browser.');
	            }
	        }
	    }
	}
}

MetastoresFragmentConnector.prototype.send = function(url, content)
{

	// send the url
	if (this.listen)
	{
		this.connector.onreadystatechange=new Function("window['metastoresFragmentListenConnector'].metastoresFragmentHandler();");
	}
	else
	{
		// call listener for request events
		if (typeof metastoresFragmentRequestEvent!='undefined')
		{
			try
			{
				metastoresFragmentRequestEvent();
			} catch (ex)
			{
				window.status='Error in fragment request event handler';
			}
		}
	
		this.connector.onreadystatechange=new Function("window['metastoresFragmentRequestConnector'].metastoresFragmentHandler();");
	}
	if (content.length>0)
	{
		//this.connector.setRequestHeader("Content-length", content.length);
		//this.connector.setRequestHeader("Connection", "close");
		this.connector.open("POST", url, true);
		this.connector.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		//Send the proper header information along with the request
		this.connector.send(content);
	}
	else
	{
		this.connector.open("GET", url, true);
		this.connector.send(content);
	}
};

MetastoresFragmentConnector.prototype.metastoresFragmentHandler = function()
{
	if (this.connector.readyState != 4)
		return;
	if (typeof metastoresFragmentReceivedEvent!='undefined')
	{
		try
		{
			metastoresFragmentReceivedEvent();
		} catch (ex)
		{
			window.status='Error in fragment received event handler';
		}
	}
	document.body.style.cursor='default';
//	if (window.metastoresFocusedElement)
//	{
//		window.metastoresFocusedElement.style.cursor='default';
//	}
	if (!this.metastoresFragmentParser(this.connector.responseText))
	{
		if (typeof window.document.forms.mainform!='undefined')
		{
			window.document.forms.mainform.submit();
		}
		else
		{
			window.location.reload(true);
		}
		return;
	}
	// stop busy style
	if (typeof busyStop!='undefined') busyStop();
	
	// reiterate a listener
	if (this.listen)
	{
		metastoresFragmentListen();
	}
};

MetastoresFragmentConnector.prototype.metastoresFragmentParser = function(s)
{
	// connection abort
	if (s.length==0)
	{
		return false;
	}
	
	if (s.indexOf("<connection-timout/>")==0)
	{
		return true;
	}	
	
	// check for correct response header

	if (s.indexOf("<metastores-ui-xhtml>")<0)
	{
		if (s.length>255)
		{
			s = s.substring(0, 255) + "...";
		}
		alert("incorrect response header: "+s);
		return false;
	}

	s=s.substring(s.indexOf("<metastores-ui-xhtml>")+"<metastores-ui-xhtml>".length);
	
	// never trust an empty response - force a complete reload then
	if (s.indexOf("</metastores-ui-xhtml>")==0)
	{
		return true;
	}
	
	// iterate through fragments

	while (true)
	{
		if (s.indexOf("<fragment target=\"")==0)
		{
			s=s.substring("<fragment target=\"".length);
			target=s.substring(0, s.indexOf("\">"));
			s=s.substring(target.length+2);
			var content=s.substring(0, s.indexOf("<"+"/fragment>"));
			s=s.substring(content.length+("<"+"/fragment>").length);
			//alert('next ' + target);
			if (document.getElementById(target)==null)
			{
				// if we can not find the fragment, better make a full refresh
				return false;
			}
			else
			{
				// check for javascript
				if (content.indexOf("<script>")==0)
				{
					content=content.substring("<script>".length);
					content=content.substring(0, content.indexOf("</script>"));
					eval(content);
				}
				else
				{
					document.getElementById(target).parentNode.innerHTML=content;
				}
			}
		}
		else if (s.indexOf("<redirect url=\"")==0)
		{
			s=s.substring("<redirect url=\"".length);
			url=s.substring(0, s.indexOf("\"/>"));
			s=s.substring(url.length+3);
			document.location.href=url;
		}
		else if (s.indexOf("<refresh/>")==0)
		{
			s=s.substring("<refresh/>".length);
			return false;
		}
		else if (s.indexOf("<no-contents/>")==0)
		{
			s=s.substring("<no-contents/>".length);
			return true;
		}
		else if (s.indexOf("</metastores-ui-xhtml>")==0)
		{
			s=s.substring("</metastores-ui-xhtml>".length);
			break;
		}
		else
		{
			if (s.length>255)
			{
				s = s.substring(0, 255) + "...";
			}
			alert("unknown response fragment '"+s+"'");
			return false;
		}
	}
	//window.setTimeout("if (typeof metastoresSetFocus!='undefined') { metastoresSetFocus(); }", 200);
	if (typeof metastoresSetPlaceholders!='undefined') metastoresSetPlaceholders(); 
	if (typeof metastoresSetFocus!='undefined') metastoresSetFocus(); 
	if (typeof tooltipDisable!='undefined') tooltipDisable();
	return true;
};

MetastoresFragmentConnector.prototype.inputElementsToUrlParameters = function(form)
{
	var result = [];
	for (var i = 0; i < form.elements.length; i++) {
		var el = form.elements[i];
		if (el.tagName.toLowerCase() == "select") {
			for (var j = 0; j < el.options.length; j++) {
				var op = el.options[j];
				if (op.selected)
					result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(op.value));
			}
		} else if (el.tagName.toLowerCase() == "textarea") {
			result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(el.value));
		} else if (el.tagName.toLowerCase() == "button") {
			result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(el.value));
		} else if (el.tagName.toLowerCase() == "input") {
			if (el.type.toLowerCase() == "file" && el.value != "") {
				form.submit();
			} else if (el.type.toLowerCase() == "checkbox" || el.type.toLowerCase() == "radio") {
				if (el.checked)
					result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(el.value));
			} else if (el.type.toLowerCase() == "submit") {
				if (el == submitButton) // is "el" the submit button that fired the form submit?
					result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(el.value));
			} else if (el.type.toLowerCase() != "button") {
				result.push("&" + metastoresEncodeURIComponent(el.name) + "=" + metastoresEncodeURIComponent(el.value));
			}
		}
	}
	return result.join('');
};

// metastores ui fragment controller end

//metastores placeholder functions - Peter Breitling

function initPlaceholder(elementId, placeholder)
{
	if (typeof window.__placeHolderByElementId=='undefined')
	{
		window.__placeHolderByElementId = new Array();
	}
	window.__placeHolderByElementId[elementId] = placeholder;
}
function metastoresSetPlaceholder(element)
{
	if (element && element.value.length == 0)
	{
		element.__placeHolder = 1;
		element.style.color = '#808080';
		element.value = window.__placeHolderByElementId[element.id];
	}
}
function metastoresUnsetPlaceholder(element)
{
	if (element && element.__placeHolder!='undefined' && element.__placeHolder!=null)
	{
		element.__placeHolder = null;
		element.style.color = '';
		element.value = '';
	}
}
function metastoresSetPlaceholders()
{
	// handle focus hint
	
	if (typeof window.__placeHolderByElementId!='undefined' && window.__placeHolderByElementId!=null)
	{
		for (elementId in window.__placeHolderByElementId)
		{
			var element=document.getElementById(elementId);
			metastoresSetPlaceholder(element);
		}
	}
}
function metastoresUnsetPlaceholders()
{
	// handle focus hint
	
	if (typeof window.__placeHolderByElementId!='undefined' && window.__placeHolderByElementId!=null)
	{
		for (elementId in window.__placeHolderByElementId)
		{
			var element=document.getElementById(elementId);
			metastoresUnsetPlaceholder(element);
		}
	}
}

// metastores placeholder functions end


//metastores tooltip functions - Peter Breitling

function tooltipInit()
{
if (typeof window.tooltipDiv=='undefined' || window.tooltipDiv==null)
{
 window.tooltipDiv=document.createElement("DIV");
 window.tooltipDiv.style.position="absolute";
 window.tooltipDiv.style.visibility="hidden";
 document.body.appendChild(window.tooltipDiv);
 tooltipFader();
}
}

function tooltipFader()
{
setTimeout('tooltipFader()', 50);
if (typeof window.tooltipDiv!='undefined' && window.tooltipDiv!=null)
{
 if (tooltipIsActive()){
   tooltipFadeIn(0.1);
 }else{
   tooltipFadeOut(0.1);
 }
 return;
}
}

function tooltipEnable()
{ 
tooltipInit();
window.tooltipDivEnabled=true;
}

function tooltipDisable()
{
tooltipInit();
window.tooltipDivEnabled=false;
}

function tooltipIsActive()
{
if (typeof window.tooltipDivEnabled!='undefined' && window.tooltipDivEnabled!=null)
{
 return window.tooltipDivEnabled;
}
return false;
}

function tooltipFadeIn(level)
{
if (typeof window.tooltipDivOpacity=='undefined' || window.tooltipDivOpacity==null)
  window.tooltipDivOpacity=0.0;
window.tooltipDivOpacity+=level;
if (window.tooltipDivOpacity>1.0)
  window.tooltipDivOpacity=1.0;
var levelFloat=window.tooltipDivOpacity;
var ieLevel=levelFloat*100;
window.tooltipDiv.style.opacity=levelFloat;
window.tooltipDiv.style.opacity=window.tooltipDivOpacity;
window.tooltipDiv.style.filter='Alpha(opacity='+ieLevel+', finishopacity='+ieLevel+', style=2)';
if (window.tooltipDivOpacity>0)
  window.tooltipDiv.style.visibility="inherit";
}

function tooltipFadeOut(level)
{
if (typeof window.tooltipDivOpacity=='undefined' || window.tooltipDivOpacity==null)
  window.tooltipDivOpacity=0.0;
window.tooltipDivOpacity-=level;
if (window.tooltipDivOpacity<-1.0)
  window.tooltipDivOpacity=-1.0;
var levelFloat=window.tooltipDivOpacity;
if (window.tooltipDivOpacity<0.0)
  levelFloat=0.0;
var ieLevel=levelFloat*100;
window.tooltipDiv.style.opacity=levelFloat;
window.tooltipDiv.style.filter='Alpha(opacity='+ieLevel+', finishopacity='+ieLevel+', style=2)';
// immediate out fade
if (true || window.tooltipDivOpacity<=0) {
  window.tooltipDiv.style.visibility="hidden";
  window.tooltipDiv.style.left=0+"px";
  window.tooltipDiv.style.right=null;
  window.tooltipDiv.style.top=0+"px";
  window.tooltipDiv.style.bottom=null;
}
}
function tooltipErrorDisplay(parentElement, x, y, text)
{
tooltipInit();
window.tooltipDiv.innerHTML='<div class="rendertooltiperrorstyle">'+text+'</div>';
tooltipMove(parentElement, x, y);
tooltipEnable();
}
function tooltipDisplay(parentElement, x, y, text)
{
tooltipInit();
window.tooltipDiv.innerHTML='<div class="rendertooltipstyle">'+text+'</div>';
tooltipMove(parentElement, x, y);
tooltipEnable();
}
function tooltipMove(parentElement, x, y)
{
// tooltipFadeOut(0.08);
var offsetX;
if (typeof window.pageXOffset!='undefined')
 offsetX=window.pageXOffset;
else
 offsetX=document.body.scrollLeft;
var offsetY;
if (typeof window.pageYOffset!='undefined')
 offsetY=window.pageYOffset;
else
 offsetY=document.body.scrollTop;
if (typeof window.tooltipDiv!='undefined' && window.tooltipDiv!=null)
{
 if (true || x * 2 < document.body.clientWidth || navigator.appName.indexOf("Opera")>=0)
 {
   window.tooltipDiv.style.right=null;
   window.tooltipDiv.style.left=x+offsetX+10+"px";
 }
 else
 {
   // if scrollLeft/Top was used then ignore it in this case
   // this is need for IE6 only (not IE7)
   if (navigator.appVersion.indexOf("MSIE 6")>=0)
     offsetX=0;
   window.tooltipDiv.style.left=null;
   window.tooltipDiv.style.right=document.body.clientWidth-offsetX-x+10+"px";
 }
 if (true || y * 2 < document.body.clientHeight || navigator.appName.indexOf("Opera")>=0)
 {
   window.tooltipDiv.style.bottom=null;
   window.tooltipDiv.style.top=y+offsetY+15+"px";
 }
 else
 {
   // if scrollLeft/Top was used then ignore it in this case
   // this is need for IE6 only (not IE7)
   if (navigator.appVersion.indexOf("MSIE 6")>=0)
     offsetY=0;
   window.tooltipDiv.style.top=null;
   window.tooltipDiv.style.bottom=document.body.clientHeight-offsetY-y+"px";
 }
}
}

function tooltipHide(parentElement)
{
if (typeof window.tooltipDiv!='undefined' && window.tooltipDiv!=null)
{
 // window.tooltipDiv.style.visibility="hidden";
 // window.tooltipDiv.style.left=0+"px";
 // window.tooltipDiv.style.right=null;
 // window.tooltipDiv.style.top=0+"px";
 // window.tooltipDiv.style.bottom=null;
}
tooltipDisable();
}

//metastores tooltip functions end

