// rev 05 Mar 2009


function select_first(type) {
    var select_type = (type || 'text');
    var which_fld   = "";
    if (document.forms[0]) {
        for (var i = 0; i < document.forms.length; i++) {
            var e=document.forms[i].elements;
            for (var n = 0; n < e.length; n++) {
                if (e[n]!=null && e[n].type) { if (e[n].type==select_type) { which_fld = e[n]; break; } } 
            }
            if (which_fld !== "") { which_fld.focus(); break; }
        }
    }
}
 
function textPreview(from,to,start,end) {
    if (document.getElementById(from) && document.getElementById(to)) {
        start   = (start) ? start : '<p>';
        end     = (end) ? end : '</p>';
        var newline = /\n/g;
        var paragraph = /\n\n/g;
        var newText = document.getElementById(from).value;
        var divPreview = document.getElementById(to);
        if (newText != "") {
            newText = newText.replace(paragraph, "</p><p>");
            newText = newText.replace(newline, "<br/>");
            divPreview.innerHTML = start + newText + end;
        } else {
            divPreview.innerHTML = "";
        }
    }
}

// Substitute for a common function
function $(id) {
	if (typeof id == "string") {
   	 return document.getElementById(id)
   	}
   	return id;
}

function trainChars (str,carLen) {
    var origStr     = str;
    var chunkLen    = carLen;
    var pos         = 0;
    return function () {
        origStr += origStr;
        pos++;
        return origStr.substring(pos,chunkLen+pos);
    }
    
}

// Cascade Factory
function cascader (tgt,src,pause,len,sep) {
    var targ	            = tgt;
	window.targ	            = new make_cascade(targ,src,pause,len);
 	window.targ.really_go	= function () {
		window.targ.go();
		setTimeout('window.targ.really_go()',window.targ.pause);
	};
	return window.targ.really_go;	
}
// Cascade Contructor  call with new make_cascade(tgt,src,pause,len,sep)
function make_cascade (tgt,src,pause,len,sep) {
    this.tgt        = tgt;
    this.src        = src;
    this.pause      = pause;
    this.len        = len;
    this.sep        = sep ? sep : '<br> ';

    var store_name  = this.tgt + '_state';
    var paramStr = "({tgt:'"    + this.tgt + 
                  "',src:'"     + this.src + 
                  "',pause:'"   + this.pause +
                  "',len:'"     + this.len +
                  "',sep:'"     + this.sep + "'})";
    
    _setV($(store_name), [paramStr]); 
};
// Cascade Action
make_cascade.prototype.go = function go () {
    var store       = this.tgt + '_state';
    var paramStr	= getItemValue(store);
    var stateObj	= eval(paramStr);

    var names		= getItemValue(stateObj.src);
    var name_list	= names.split(" |");
    var thisName	= name_list.pop();
    name_list.unshift(thisName);
    var rev_names	= name_list.join(" |");

    var show_names	= name_list.slice(0,stateObj.len);
    show_names[0]	= "<span class='scroll_first'>" + show_names[0] + '<\/span>';
    var new_str		= show_names.join(stateObj.sep);

    _setV($(stateObj.tgt), [new_str]);
    _setV($(stateObj.src), [rev_names]);
};



// set a style attribute of an HTML element identified by id
function setItemStyle (id,selector,val) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (!item) { return }
	if (!selector) { return }
	if (!"selector" in item.style) { return } 
    
	item.style[selector] = val;
    
    return val;
}


// set value of an HTML element identified by id
function setItemValue (id,val) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (item != null) {
		var ret     = _setV(item,[val]);
    }
    
    return ret;
}


// append value to an HTML element identified by id
function appendItemValue (id,val) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (item != null) {
		var ret     = _setV(item,[val], '+');
    }
    
    return ret;
}


// clear contents of an HTML element identified by id
function clearItem (id) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (item != null) {
		var ret     = _setV(item,['']);
    }
    
    return ret;
}


// get single value from an HTML element identified by id
// (first only if source returns multiple values)
function getItemValue (id) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (item != null) {
		var ret     = _getV(item);
		if (ret.srcStat[0] == 'OK') {
			return ret.vals[0];
		}
    }
    
    return "";
}

// get multiple values from an HTML element identified by id
function getItemValues (id) {
    var item        = null;
    if (document.getElementById) {
        item    = document.getElementById(id);
    } else if (document.all) {
        item    = document.all[id];
    }
    
    if (item != null) {
		var ret     = _getV(item);
		if (ret.srcStat[0] == 'OK') {
			return ret.vals;
		}
    }
    
    return [];
}

// get single value from an HTML element identified by tagname and index
// (first only if source returns multiple values)
function getElemValue (tag,idx) {
    var item        = null;
    idx             = (idx) ? idx : 0;
    if (document.getElementsByTagName) {
        item    = document.getElementsByTagName(tag)[idx];
    } else if (document.all) {
        item    = document.all.tags(tag)[idx];  
    }
    
    if (item != null) {
		var ret     = _getV(item);
		if (ret.srcStat[0] == 'OK') {
			return ret.vals[0] || "" ;
		}
    }
    
    return [];
}

// get multiple values from an HTML element identified by tagname and index
function getElemValues (tag,idx) {
    var item        = null;
    idx             = (idx) ? idx : 0;
    if (document.getElementsByTagName) {
        item    = document.getElementsByTagName(tag)[idx];
    } else if (document.all) {
        item    = document.all.tags(tag)[idx];  
    }
    
    if (item != null) {
		var ret     = _getV(item);
		if (ret.srcStat[0] == 'OK') {
			return ret.vals;
		}
    }
    
    return [];
}

// Get values from various elements
function _getV (item) {
    var itemVals    = [""];
	if (!item || item == null) { 
		return { vals:itemVals, srcStat:['Error', 'No item,'] }
	}
    var itemRef   = item.type || item.tagName || '';
	if (!itemRef || itemRef == null) { 
		return { vals:itemVals, srcStat:['Error', 'Unknown item.'] }
	}
    var whichItem   = String( itemRef ).toUpperCase();
    switch ( whichItem ) {
        case 'TEXT':
            itemVals    = [item.value];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'HIDDEN':
            itemVals    = [item.value];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'TEXTAREA':
            itemVals    = [item.value];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'PASSWORD':
            itemVals    = [item.value];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'BUTTON':
            itemVals    = [item.value];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'SELECT-ONE':
            itemVals    = (item.selectedIndex > -1) ? [ item.options[item.selectedIndex].value || item.options[item.selectedIndex].text ] : [""];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'SELECT-MULTIPLE': 
            var idx         = 0;
            var itemArray   = [];
            for (var i = 0; i < item.options.length; i++) {
                if (item.options[i].selected) {
/*                     itemVals[idx++] = (item.options[i].value) ? item.options[i].value : item.options[i].text; */
                    itemArray[idx++] = (item.options[i].value) ? item.options[i].value : item.options[i].text;
                }
            }
            itemVals    = [itemArray.join(',')];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'CHECKBOX':
            itemVals    = item.checked ? [1] : [0];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'RADIO':
            var thisRadio   = item.form.elements[item.name];
            for (var i = 0; i < thisRadio.length; i++) {
                if (thisRadio[i].checked) {             
                    itemVals    = [thisRadio[i].value];
                    break;
                }
            }
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'P':
            itemVals    = [item.innerHTML];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'DIV':
            itemVals    = [item.innerHTML];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'SPAN':
            itemVals    = [item.innerText];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        case 'FORM':
            itemVals    = [item.innerHTML];
            return { vals:itemVals, srcStat:['OK', whichItem] };
        default:
            return { vals:itemVals, srcStat:['Error', 'Unknown item reference: ' + whichItem] };
    }
}


// Get META elements of document, returned as an object/hash
function getMeta () {
    var docMeta = {};
    var metaElements;
    if (document.all) {
    	metaElements = document.all.tags('META');
    } else if (document.getElementsByTagName) {
    	metaElements = document.getElementsByTagName('META')
    } else {
    	metaElements = new Array();
    }
    for (var i = 0; i < metaElements.length; i++) {
        docMeta[metaElements[i].name]   = metaElements[i].content;
    }
    return docMeta;
}

// Get document keywords, returned as an array
function getMetaKeywords () {
    var metaKeywords = getMeta().keywords || [];
    return metaKeywords;
}

// Get the target of an event, mostly browser-proof
function getEventTarget (evt) {
    var targ;
    
    if (evt.target) {
        targ = evt.target;
    } else if (evt.currentTarget) {
        targ = evt.currentTarget;
    } else if (evt.srcElement) {
        targ = evt.srcElement;
    }
    // defeat Safari bug:
    if (targ.nodeType == 3) {
        targ = targ.parentNode;
    }

    return targ;
}

// Set or append values in various elements
function _setV (item,vals,mode,sep) {
    if (!item) { return ""; };
    var whichItem   = String( item.type || item.tagName ).toUpperCase();
    var newVals     = (vals) ? vals : [""];
    var append      = (mode == '+' || mode == 'add') ? true : false;
    var appendSep;
    var oldVals     = [];
    switch ( whichItem ) {
        case 'TEXT':
            oldVals = [item.value];
            appendSep	= (sep) ? sep : ' ';
            item.value  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals[0] : newVals[0];
            return item.value;
        case 'HIDDEN':
            oldVals = [item.value];
            appendSep	= (sep) ? sep : ' ';
            item.value  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals[0] : newVals[0];
            return item.value;
        case 'TEXTAREA':
            oldVals = [item.value];
            appendSep	= (sep) ? sep : "\n";
            item.value  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals[0] : newVals[0];
            return item.value;
        case 'PASSWORD':
            oldVals = [item.value];
            appendSep	= (sep) ? sep : ' ';
            item.value  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals[0] : newVals[0];
            return item.value;
        case 'BUTTON':
            oldVals = [item.value];
            appendSep	= (sep) ? sep : ' ';
            item.value  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals[0] : newVals[0];
            return item.value;
        case 'SELECT-ONE':
            for (var i = 0; i < item.options.length; i++) {
                if (item.options[i].value == newVals[0]) {
                    item.selectedIndex  = i;
                    break;
                }
            }
            return newVals[0];
        case 'SELECT-MULTIPLE': 
            if (!append) { item.selectedIndex   = -1 }
            for (var v = 0; v < newVals.length; v++) {
                for (var i = 0; i < item.options.length; i++) {
                    if (item.options[i].value == newVals[v]) {
                        item.options[i].selected = true;
                    }
                }
            }
            return newVals;
        case 'CHECKBOX':
            oldVals = [item.checked];
            item.checked    = (newVals[0]) ? true : false;
            return item.checked;
        case 'RADIO':
            var thisRadio   = item.form.elements[item.name];
            for (var i = 0; i < thisRadio.length; i++) {
                if (thisRadio[i].value == newVals[0]) {             
                    thisRadio[i].checked = true;
                    break;
                }
            }
            return newVals[0];
        case 'P':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H1':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H2':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H3':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H4':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H5':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'H6':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'DIV':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'SPAN':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        case 'FORM':
            oldVals = [item.innerHTML];
            appendSep		= (sep) ? sep : "<br />\n";
            item.innerHTML  = (append && oldVals[0]) ? oldVals[0] + appendSep + newVals.join(appendSep) : newVals.join(appendSep);
            return item.innerHTML;
        default:
            return "";
    }
}


// XHR Methods

// XHR GET
 function xhrGet(action,args,OKprocs,verbose,preProcs,postProcs,reqTime) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    var timeLimit	= reqTime ? reqTime : 90000;

    var request = _xhr('GET',url,0,params,OKprocs,preProcs,postProcs,timeLimit);
    
    var result	= request.result();
    
    switch (result.status) {
        case 'EXEC':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;   
        case 'TEXT':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;     
        case 'XML':
            if (verbose) { alert(result.status + "\n" + result.value + "\n" + result.msg) }
            return false;       
        case 'OK':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;       
        case 'ERR':
            if (verbose) { alert(result.status + "\n" + result.err) }
            return true;        
        case 'INIT':
            if (verbose) { alert(result.status + "\n" + result.err) }
            return true;        
        default:
            return true;
    }
}

// XHR RETRIEVE
 function xhrRetrieve(action,args,OKprocs,verbose,preProcs,postProcs) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    var request = _xhr('GET',url,1,params,OKprocs,preProcs,postProcs);
    
    return request.xhrText();    
}

// XHR FCN
 function xhrFcn(action,args,OKprocs,verbose,preProcs,postProcs) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    var request = _xhr('GET',url,1,params,OKprocs,preProcs,postProcs);
    
	var result	= request.xhrText();
   
	var result_fcns = eval('(' + result + ')');
    
	result_fcns	= result_fcns ? result_fcns : [{fcn:'updateItem', tgt:'xhr_msg', val:'No functions returned.'}];
       
    request.process(result_fcns);
    
    return false;
}

// XHR FORM FCN
 function xhrFormFcn(action,args,form,OKprocs,verbose,preProcs,postProcs,reqTime) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    if (form) {
        var formVals	= "";
        for (var i = 0; i < form.elements.length; i++) {
            if (!form.elements[i].name) { continue }
            formVals += form.elements[i].name + "=" + encodeURIComponent(_getV(form.elements[i]).vals[0]) + ";";
        }
        if (formVals) { params += formVals }
    }
    
    var timeLimit	= reqTime ? reqTime : 90000;
    
    var request = _xhr('POST',url,1,params,OKprocs,preProcs,postProcs,timeLimit);
        
	var result	= request.xhrText();
   
	var result_fcns = eval('(' + result + ')');
    
	result_fcns	= result_fcns ? result_fcns : [{fcn:'updateItem', tgt:'xhr_msg', val:'No functions returned.'}];
       
    request.process(result_fcns);
    
    return false;
}

// XHR OBJ
 function xhrObj(action,args,OKprocs,verbose,preProcs,postProcs) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    var request = _xhr('GET',url,1,params,OKprocs,preProcs,postProcs);
    
	var result	= request.xhrText();
   
	var result_obj = eval('(' + result + ')');
	
	var result_val	= (result_obj.val) ? result_obj.val : "";
	
	var result_fcns	= (result_obj.fcns) ? result_obj.fcns : [{fcn:'updateItem', tgt:'xhr_msg', val:'No object returned.'}];
           
    request.process(result_fcns);
    
    return false;
}

// XHR LINK
 function xhrLink(action,args,OKprocs,verbose,preProcs,postProcs) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    var request = _xhr('GET',url,0,params,OKprocs,preProcs,postProcs);
    
    void 0;    
}

// XHR REFRESH
 function xhrRefresh(action,args,OKprocs,interval,verbose,preProcs,postProcs) {  
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    interval	= interval ? interval : 1000;
    
    if (args) { params += args + ';'}
    
    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";
        
	var refresh	= setInterval(function(){
		_xhr('GET',url,1,params,OKprocs,preProcs,postProcs)
	},interval);

    return false;
}

function formParams (form) {
	var thisForm	= form;
	var formLen		= thisForm.elements.length;
	if (!formLen) { return '' }
	var params		= '';
	for (var i = 0; i < formLen; i++) {
		if (!thisForm.elements[i].name) { continue }
		params += thisForm.elements[i].name + '=' + encodeURIComponent(_getV(thisForm.elements[i]).vals[0]) + ';';
	}
	return params;
}



// XHR POST
function xhrPost(action,args,form,OKprocs,verbose,preProcs,postProcs,reqTime) { 
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    var url		= '';
    if (args) { params += args + ';'}

    params		+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";

    if (form) {
        var formVals	= "";
        for (var i = 0; i < form.elements.length; i++) {
            if (!form.elements[i].name) { continue }
            formVals += form.elements[i].name + "=" + encodeURIComponent(_getV(form.elements[i]).vals[0]) + ";";
        }
        if (formVals) { params += formVals }
    }
    
    var timeLimit	= reqTime ? reqTime : 90000;
    
    var request = _xhr('POST',url,0,params,OKprocs,preProcs,postProcs,timeLimit);
    
    var result	= request.result();
    
    switch (result.status) {
        case 'EXEC':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            if (request.output) { return result.returnVals }
            return false;   
        case 'TEXT':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;     
        case 'XML':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;       
        case 'OK':
            if (verbose) { alert(result.status + "\n" + result.msg) }
            return false;       
        case 'ERR':
            if (verbose) { alert(result.status + "\n" + result.err); }
            return true;        
        case 'INIT':
            if (verbose) { alert(result.status + "\n" + result.err) }
            return true;        
        default:
            return true;
    }
}
 
// Main XHR Request method
function _xhr (method,exec_url,reqSync,params,reqOKProcs,preProcs,postProcs,reqTime,reqTimeProcs,noReqProcs,noExecProcs) {   

    var ex			= new xhrExec(exec_url);
    
    noReqProcs		= noReqProcs ? noReqProcs : [{fcn:'xhrReportErr', val:'No Request Object Available.'}];
        
    if (!ex.getXHRequest()) {
   		ex.process(noReqProcs); 
   		return ex;
	}
	
	noExecProcs		= noExecProcs ? noExecProcs : [{fcn:'xhrReportErr', val:'No Remote Executable:'}];
	
	if (!ex.getExec()) {
    	ex.status = "ERR";
        ex.process(noExecProcs);
        return ex;
    }
    	
	method			= method ? method : 'GET';
	
	var aSync		= reqSync? false : true;
	
	reqOKProcs		= reqOKProcs ? reqOKProcs : [{fcn:'direct'}];
	
	preProcs		= preProcs ? preProcs : [{fcn:'xhrReportMsg', val:'Ready (' + ex.dom + ').'}];
	
	postProcs		= postProcs ? postProcs : [{fcn:'xhrReportMsg', val:'Done.'}];
	
	reqTime			= reqTime ? reqTime : 90000;
	reqTimeProcs	= reqTimeProcs ? reqTimeProcs : [{fcn:'xhrAbort', val:'HTTP Request Timed Out.'}];
		
	ex.process(preProcs);

	ex.timeout      = setTimeout(function () {
		ex.process(reqTimeProcs);   
	}, reqTime);    
	
	ex.request.onreadystatechange = function () {
		if (ex.request.readyState == 4) {
		    ex.msg  += ex.request.readyState;
			clearTimeout(ex.timeout);
			if (ex.request.status == 200) {
				if (aSync) {
					ex.process(reqOKProcs);
				}
			} else {
				ex.err  += "Retrieval failure:\n" + ex.request.statusText + "\n";
			}
		} else {
			ex.msg  += ex.request.readyState + " - ";
		}
	}
		
	if (method == "GET") {
		var url =   ex.makeExecURL(params);
		ex.request.open("GET", url, aSync);
		ex.request.send("");
		if (!aSync) {
			ex.process(reqOKProcs);
		}

	} else if (method == "POST") {
		var url =   ex.makeExecURL();
		ex.request.open("POST", url, aSync);
		ex.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		ex.request.send(params);
		if (!aSync) {
			ex.process(reqOKProcs);
		}
	
	} else if (method == "HEAD") {
		var url =   ex.makeExecURL(params);
		ex.request.open("HEAD", url, aSync);
		ex.request.send("");
		if (!aSync) {
			ex.process(reqOKProcs);
		}
		
	} else if (method == "PUT") {
		ex.err  += "Unsupported http request method: " + method;
		ex.status = "ERR";
		
	} else {
		ex.err  += "Unknown http request method: " + method;
		ex.status = "ERR";
	}
	
	ex.process(postProcs);

    return ex;
}

// OBJ
 function objLoadSrc(object,action,args,OKProcs,preProcs,postProcs) { 
 
 	object		= (object) ? object : getEventTarget(event);

    var url		= '';
 	
    var params  = (action) ? 'action=' + encodeURIComponent(action) + ';' : ""; 
    if (args) { params += args + ';'}    
    params	+= (getItemValue('do_test')) ? 'SYS:do_test=1;' : "";
    
    OKProcs		= OKProcs ? OKProcs : [{fcn:'xhrReportMsg', val:'Source loaded OK'}];

    var ex = _obj(object,'SRC',url,params,OKProcs,preProcs,postProcs);
    
    return false;
}

// Main OBJECT method
function _obj (object,method,exec_url,params,objOKProcs,objPreProcs,objPostProcs) {   

    var ex			= new xhrExec(exec_url);
        
	var noExecProcs	= [{fcn:'xhrReportErr', val:'No Remote Executable:'}];
	
	if (!ex.getExec()) {
    	ex.status = "ERR";
        ex.process(noExecProcs);
        return ex;
    }
    	
	method			= method ? method : 'SRC';
	
	objOKProcs		= objOKProcs ? objOKProcs : [{fcn:'xhrReportMsg', val:'OK'}];
	
	objPreProcs		= objPreProcs ? objPreProcs : [{fcn:'xhrReportMsg', val:'Ready.'}];
	
	objPostProcs	= objPostProcs ? objPostProcs : [{fcn:'xhrReportMsg', val:'Done.'}];
	
	ex.process(objPreProcs);
			
	if (method == "SRC") {
		ex.objURL =   ex.makeExecURL(params);
		ex.process([{fcn:'setItemSrc',tgt:object}]);
		ex.process(objOKProcs);
		
	} else {
		ex.err  += "Unknown http object method: " + method;
		ex.status = "ERR";
	}
	
	ex.process(objPostProcs);

    return ex;
}


// The core executable object constructor -- call with "new xhrExec (url)".
// See prototypes below for methods.
function xhrExec (url) {
    // Initial values for the executable object
    this.status        = "INIT";
    this.returnVals    = [];
    this.msg           = "";
    this.err           = "";    
}

// XHR Executable Object Methods
// Prototypes for xhrExec

xhrExec.prototype.getXHRequest    = function() {
    try {
		this.request   	= new XMLHttpRequest();
		this.dom		    = "W3C-STD";
	} catch(e) {
		try {
			this.request   	= new ActiveXObject("Msxml2.XMLHTTP");
		    this.dom		= "IE6";
		} catch(e) {
			try {
				this.request   	= new ActiveXObject("Microsoft.XMLHTTP");
		        this.dom		= "IE5";
			} catch(e) {
				this.err	        += "XHR Object initialization failed: " + e + "\n";
				this.status			= 'ERR';
				this.dom		    = "Unknown";
				return false;
			}
		}
	}
	return true;
};

// Again, using heuristic to get the DOM, choose a dom-specific method for identifying an item during processing
     // Try IE/Windows ActiveX (IEx DOM) 
xhrExec.prototype.getItem    =  (window.ActiveXObject) ? 
	function () {
		var item;
		if (this.processObj) {
			item    = this.processObj.itm ? 
						this.processObj.itm :
					(this.processObj.tgt && document.all[this.processObj.tgt]) ?
						document.all[this.processObj.tgt] :
					(this.processObj.tag && document.all.tags(this.processObj.tag)) ?
						 document.all.tags(this.processObj.tag)[this.processObj.idx || 0] :
					null;
		}
		return item;
	} :
	// Otherwise, assume standards (W3C DOM)
	function () {
		var item;
		if (this.processObj) {
			item    = this.processObj.itm ? 
						this.processObj.itm :
					(this.processObj.tgt && document.getElementById(this.processObj.tgt)) ? 
						document.getElementById(this.processObj.tgt) :
					(this.processObj.tag && document.getElementsByTagName(this.processObj.tag) ) ?
						document.getElementsByTagName(this.processObj.tag)[this.processObj.idx || 0] : 
					null;
		}
		return item;
	};

xhrExec.prototype.getExec	= function (url) {

    // Get the XHR executable
    
    // Determine the URL of the XHR executable
    if (url) {
        this.execSrc	= 'url';
    } else if (window.cgi) {
        // allow use of top-level variables cgi, exec, and sid
        url         			= window.cgi + ((window.sid) ? "/" + window.sid : "");
        this.execSrc	= 'wcgi';
    } else if (window.exec) {
        // cgi & exec are used the same way, as the URL of the executable
        url         			= window.exec + ((window.sid) ? "/" + window.sid : "");
        this.execSrc	= 'wexec';
    } else if (getMeta().xhr_exec) {
        // the executable may be specified as a META element, name = xhr_exec
        url         			= getMeta().xhr_exec;
        url         			+= (getMeta().xhr_sid) ? "/" + getMeta().xhr_sid : (window.sid) ? "/" + window.sid : "";
        this.execSrc	= 'meta';
    } else {
		// use the document's own url
        url         			= (document.URL) ? document.URL : document.location;
        this.execSrc	= 'doc';
    } 
    
    // Parse and check the URL                              
    if (url) {
        var execRE  = /^(.*\/([^\.\/]+\.(cgi|pl|exe|scpt)))\/?(([^\?]+)\??(.*))?$/i;    
        var res     = execRE.exec(url);
        
        if (res) {
            this.origURL       = res[0];
            // properties cgi & exec have the same value in this object instance
            this.cgi           = res[1];
            this.exec          = res[1];
            this.scriptName    = res[2];
            this.scriptSuf     = res[3] || "";
            this.queryStr      = res[4] || "";
            this.sid           = res[5] || "";
            this.args          = res[6] || "";
        } else {
            this.err   += "Source URL failed to yield known executable:\n" + url + "\n";
            return false;
        }   
    } else {
        this.err   	+= "No source URL.\n";  
        return false;
    }
    this.msg       += "OK. Executable loaded (" + this.execSrc + "). - ";
    this.status    = "EXEC";

    return true;
}

			
// A method to handle callbacks at any stage of execution
xhrExec.prototype.process       = function (processObjects) {
	for (var i = 0; i < processObjects.length; i++) {
		// check
		if (processObjects[i].fcn) {	
			// Assign this process object and its function to the executable object
			this.processObj     = processObjects[i];
			this.processFcn     = (this[processObjects[i].fcn]) ? this[processObjects[i].fcn] : processObjects[i].fcn;
			// Execute the process, capturing any result value
			this.returnVals[i]  = this.processFcn();
		}
	}
}; 

// A method to stringify the executable object
xhrExec.prototype.toString		= function () {
	return	"Status: " + this.status + "\n" +
		((this.msg) ? "Msg: " + this.msg + "\n" : "") +
		((this.err) ? "Err: " + this.err + "\n" : "") +
		this.returnVals.join("\n");
};

// A method to stringify the result array
xhrExec.prototype.resToString		= function () {
	return this.returnVals.join("\n");
};

// A method to get the result (current state, really) from the executable
xhrExec.prototype.result		= function () {
	return {msg:this.msg, err:this.err, status:this.status, returnVals:this.returnVals};
};
	 
xhrExec.prototype.xhrAbort		= function () {
	this.status     = 'ERR';
	this.request.abort();
	this.err        += this.val || 'Aborted';
	window.status   = this.err;
 }

xhrExec.prototype.xhrReportErr	= function () {
	this.status     = 'ERR';
	window.status   = this.err + ((this.processObj.val) ? '  ' + this.processObj.val : '');
	this.err        += (this.processObj.val) ? ' - ' + this.processObj.val : '';  
}

xhrExec.prototype.xhrReportMsg	= function () {
	window.status   = this.msg + ((this.processObj.val) ? '  ' + this.processObj.val : this.status);
	this.msg        += ((this.processObj.val) ? this.processObj.val : this.status) + " - ";   
}

xhrExec.prototype.say	= function () {
    alert(this.processObj.val)
}


// A method for assembling the executable's url on the fly
xhrExec.prototype.makeExecURL   = function (args) {
	var exURL       = this.cgi;
	exURL           += (this.sid) ? '/' + this.sid : "";
	exURL           += (args) ? '?' + args : "";
	return exURL;
};
		   
xhrExec.prototype.clearItem    = function () {
	return _setV(this.getItem(), [""]);
};

xhrExec.prototype.clearElem    = function () {
	return _setV(this.getItem(), [""]);
};

xhrExec.prototype.updateItem    = function () {
	return _setV(this.getItem(), [(this.processObj.val) ? this.processObj.val : this.request.responseText]);
};

xhrExec.prototype.setItemSrc    = function () {
	var obj		= this.getItem();
	if (!obj) {
		this.err        += 'No object!';
		window.status   = this.err;
		return;
	}
	var srcURL	= (this.processObj.url) ? this.processObj.url : (this.objURL) ? this.objURL : this.exec;
	try {
		obj.src	= srcURL;
	} catch (e) {
		this.err        += 'Source not set: ' + e;
		window.status   = this.err;
		return;
		}
	return 1;
};

xhrExec.prototype.clearItemSrc    = function () {
	var obj		= this.getItem();
	if (!obj) { 
		this.err        += 'No object!';
		window.status   = this.err;
		return;
	}
	try {
		obj.src	= "";
	} catch (e) {
		this.err        += 'Source not cleared: ' + e;
		window.status   = this.err;
		return;
		}
	return 1;
};

xhrExec.prototype.setItemStyle	= function () {
	var item		= this.getItem();
	var selector	= (this.processObj.sel) ? this.processObj.sel : '';
	
	if (!item) { return }
	if (!selector) { return }
	if (!"selector" in item.style) { return } 

	item.style[selector] = ((this.processObj.val) ? this.processObj.val : '');
    
    return this.processObj.val;
};

xhrExec.prototype.direct    = function () {
	return (this.processObj.val) ? this.processObj.val : this.request.responseText;
};

xhrExec.prototype.updateItemXML = function () {
	var thisXML	= (this.processObj.val) ? this.processObj.val : this.request.responseXML;
	thisXML		= (thisXML) ? thisXML : "<?xml version=\"1.0\"?><result><value>No XML Data Returned. </value><status>OK</status></result>";
	return _setV(this.getItem(), [thisXML]);
};

xhrExec.prototype.updateElem    = function () {
	return _setV(this.getItem(), [(this.processObj.val) ? this.processObj.val : this.request.responseText]);
};

xhrExec.prototype.appendToItem  = function () {
	var val  = (this.processObj.val) ? this.processObj.val : this.request.responseText;
	var sep  = (this.processObj.sep) ? this.processObj.sep : "<br />";
	return _setV(this.getItem(), [val],'+',sep);
};

xhrExec.prototype.appendToElem  = function () {
	var val  = (this.processObj.val) ? this.processObj.val : this.request.responseText;
	var sep  = (this.processObj.sep) ? this.processObj.sep : "<br />";
	return _setV(this.getItem(), [val],'+',sep);
};

xhrExec.prototype.addSelect	= function() {
	var val  = (this.processObj.val) ? this.processObj.val : this.request.responseText; 
	var thisItem	= this.getItem();
	var itemType   = String( thisItem.type || thisItem.tagName ).toUpperCase();
	if (itemType != 'SELECT-ONE') {return 1}
	
	var numOpts = thisItem.options.length;
	thisItem.options.length++;
	thisItem.options[numOpts].value=val[0];
	thisItem.options[numOpts].innerHTML=val[1];
	thisItem.selectedIndex = numOpts;
	return 1;
};

xhrExec.prototype.focusItem     = function () {
	var item	= this.getItem();
	if (item != null) { return item.focus() }
	return 1;
};       

xhrExec.prototype.xhrText		= function () {
	return this.request.responseText || "";
}

xhrExec.prototype.xhrXML		= function () {
	return this.request.responseXML || "<?xml version=\"1.0\"?><result><value>No XML Data Returned</value><status>OK</status></result>";
}



