// AJAX collapsible elements (ace) client functions
//
// AJAX collapsible elements allow for the dynamic loading of page elements
// that do not need to be displayed (or loaded) at when the page is loaded.
// This permits complex pages to load quickly and take advantage of browser
// caching of page subsections.
//
// The server needs only send the part of the element that is to be displayed
// at load time, and additional content will be loaded and displayed as required
// when the element is clicked by the user.  Load requests may be broken into
// blocks for large elements; the block size is controlled on the server side.
// As this functionality will not work without javascript, a link should generally
// be provided as a means of loading a page with the content present and expanded.
//
//
// A good example of the use of this functionality is browsable menu trees
// using expandable ul tags.  The tree is structured by class, with the id
// of each loadable element specifying the branching through the tree to
// its children.  The class "ace_load" specifies <li>s that contain further
// levels to be loaded.  This class is cleared when the load completes.
// a fully-expanded, not-yet loaded tree format would be:
// <ul id="root">
//   <li>simple</li>
//   <li class="ace_load collapsed" id="root_0">
//     <ul>
//       <li id="root_0_0"></li>
//       ...
//     </ul>
//   </li>
//   ...
// </ul>

// backward-compatible encodeURIComponent
if(!window.encodeURIComponent){window.encodeURIComponent=function(a){return(escape(a));};}

// Simple generic rpc function - builds get request with function name (fcn) and args,
// issues request to url, calls back specified callback function (cb).  Silent failure.
// references on XMLHttpRequest: wikipedia
function ace_xmlhttp_rpc(url,fcn,args,cb){
	var x=null;var i;
	url+=((url.indexOf('?')==-1)?'?':'&')+'ace_fcn='+encodeURIComponent(fcn);
	for(i=0;i<args.length;i++){url+='&ace_args[]='+encodeURIComponent(args[i]);}
	if(window.XMLHttpRequest){x=new XMLHttpRequest();}
	else if(window.ActiveXObject){x=new ActiveXObject("Microsoft.XMLHTTP");}
	if(!x){return(false);}
	x.open('GET',url,true);
	x.onreadystatechange=function(){if(x.readyState==4 && x.status==200){cb.response(x.responseText);}};
	x.send(null);
	return(true);
}

// Function to insert the response XMLHttpRequest into the parent element
// and clear the appropriate ace_load class. Also responsible for
// loading additional blocks at this level if needed.
// Expects xml tags:
// element_id - id of element to insert into
// content - what to insert
// block_id - block id of this block
// next_id - id of next block to load, or 'final'
//
function ace_loader(url, fcn) {
	this.url=url;
	this.fcn=fcn;
	this.partial=new Object();
	this.loaded='hiho ';
	this.request=function(id, block){ace_xmlhttp_rpc(this.url,this.fcn,[id,block],this);}
	this.response=function(reply){
		var head=reply.slice(0,reply.indexOf("\n")).split(' ')
		if (this.loaded.lastIndexOf(head[0])==-1) {
			var body=reply.slice(reply.indexOf("\n")+1);
			if(head[2]!='final'){
				this.partial[head[0]]+=body;
				this.request(head[0], head[2]);
			} else {
				this.loaded+=head[0]+' ';
				var x=document.getElementById(head[0]);
				x.innerHTML+=(this.partial[head[0]]||'')+body;
				this.partial[head[0]]='';
				x.className=x.className.replace('ace_load','');
			}
		}
	}
}

// Onclick handler - expand/collapse/load on element click.
function ace_trigger(e){
	var x=(e)?e.target:window.event.srcElement;
	while((x.className||'').indexOf('ace_ascend')>-1){x=x.parentNode;}
	if((x.className||'').indexOf('ace_load')>-1){this.ace_loader.request(x.id,0);}
	if((x.className||'').indexOf('expanded')>-1){x.className=x.className.replace('expanded','collapsed');}
	else if((x.className||'').indexOf('collapsed')>-1){x.className=x.className.replace('collapsed','expanded');}
}

// Onload function to setup click handler
function ace_initialize(types){
	if (!document.getElementsByTagName){return;}
	var x;var i;var j;
	for(i in types){
		x=document.getElementsByTagName(i);
		for(j=0;j<x.length;j++){
			if((x[j].className||'').indexOf(types[i][0])>-1){
				x[j].onclick=ace_trigger;
				x[j].ace_loader=new ace_loader(types[i][1],types[i][2]);
			}
		}
	}
}
