function AutoSuggestControl() {
    
    this.cur = -1;
    this.layer = null;
	this.provider = arguments[0];

	// require the textboxid
	if (arguments[1]['textboxid']) { this.textbox = getEl(arguments[1]['textboxid']); }
	else { alert('Textbox id not specified.'); return false; }

	// check for hidden id
	this.hidinput = (arguments[1]['hiddenid'])?getEl(arguments[1]['hiddenid']):false;

	// check for nextfunction (calls another function when a value is selected)
	this.nextfunction = (arguments[1]['nextfunction'])?arguments[1]['nextfunction']:false;
	
	if(arguments[1]['delimeter'] && arguments[1]['delimeter'].length) {
		this.bMultipleItems = true;
		this.sDelimChar = arguments[1]['delimeter'];
	} else {
		this.bMultipleItems = false;
	}

    this.init();
}

AutoSuggestControl.prototype.autosuggest = function (aSuggestions, bTypeAhead) {
    if (aSuggestions.length > 0) {
        if (bTypeAhead) { this.typeAhead(aSuggestions[0][1]); }
        this.showSuggestions(aSuggestions);
    } else {
        this.hideSuggestions();
    }
}

AutoSuggestControl.prototype.createDropDown = function () {
    var oThis = this;
	var oNode = this.textbox;

    //create the layer and assign styles
    this.layer = document.createElement('div');
    this.layer.className = 'suggestions';
    this.layer.style.display = 'none';

    this.layer.onmouseover = 
    this.layer.onmouseup = 
    this.layer.onmousedown = function (oEvent) {
        oEvent = oEvent || window.event;
        oTarget = oEvent.target || oEvent.srcElement;
   	    if (oEvent.type == 'mouseover') { oThis.highlightSuggestion(oTarget); }
   	    if (oEvent.type == 'mousedown') { oThis.setValue(oTarget); }
   	}
    
    document.body.appendChild(this.layer);
}

AutoSuggestControl.prototype.getLeft = function () {

    var oNode = this.textbox;
    var iLeft = 0;
    
    while(oNode.tagName != 'BODY') {
        iLeft += oNode.offsetLeft;
        oNode = oNode.offsetParent;        
    }
    
    return iLeft;
}

AutoSuggestControl.prototype.getTop = function () {

    var oNode = this.textbox;
    var iTop = 0;
    
    while(oNode.tagName != 'BODY') {
        iTop += oNode.offsetTop;
        oNode = oNode.offsetParent;
    }
    
    return iTop;
}

AutoSuggestControl.prototype.handleKeyDown = function (oEvent) {
    switch(oEvent.keyCode) {
        case 38: //up arrow
            this.previousSuggestion();
            break;
        case 40: //down arrow 
            this.nextSuggestion();
            break;
        case 13: //enter
            this.hideSuggestions();
			try { eval(this.nextfunction); }
			catch (err) { }
            break;
    }
}

AutoSuggestControl.prototype.handleKeyUp = function (oEvent) {
    var iKeyCode = oEvent.keyCode;

    //for backspace (8) and delete (46), shows suggestions without typeahead
    if (iKeyCode == 8 || iKeyCode == 46) {
        this.provider.requestSuggestions(this.textbox.value, this, false);
        
    //make sure not to interfere with non-character keys
    } else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123)) {
        //ignore
    } else {
        //request suggestions from the suggestion provider with typeahead
        this.provider.requestSuggestions(this.textbox.value, this, true);
    }
}

AutoSuggestControl.prototype.hideSuggestions = function () {
    this.layer.style.display = 'none';
	this.layer.innerHTML = '';
	this.cur = -1;
//	this.textbox.focus();
}

AutoSuggestControl.prototype.highlightSuggestion = function (oSuggestionNode) {
    
    for (var i=0; i < this.layer.childNodes.length; i++) {
        var oNode = this.layer.childNodes[i];
        if (oNode == oSuggestionNode) {
            oNode.className = 'current'
        } else if (oNode.className == 'current') {
            oNode.className = '';
        }
    }
}

AutoSuggestControl.prototype.init = function () {
    //save a reference to this object
    var oThis = this;
    
    //assign the onkeyup event handler
    this.textbox.onkeyup = function (oEvent) {
    
        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }    
        
        //call the handleKeyUp() method with the event object
        oThis.handleKeyUp(oEvent);
    }
    
    //assign onkeydown event handler
    this.textbox.onkeydown = function (oEvent) {
    
        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }    
        
        //call the handleKeyDown() method with the event object
        oThis.handleKeyDown(oEvent);
    }

    //assign onblur event handler (hides suggestions)    
    this.textbox.onblur = function () {
        oThis.hideSuggestions();
    }

    //create the suggestions dropdown
    this.createDropDown();
}

AutoSuggestControl.prototype.nextSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) {
        var oNode = cSuggestionNodes[++this.cur];
        this.highlightSuggestion(oNode);

		this.setValue(oNode);
    }
}

AutoSuggestControl.prototype.setValue = function (oNode) {
	var oTextbox = this.textbox;
	if(this.bMultipleItems && this.sDelimChar) {
		//if(this.provider._caretPos.startText) {
			oTextbox.value = this.provider._caretPos.startText || '';
		//}
		//console.log(this.provider._caretPos.startText, oTextbox.value);
		oTextbox.value += oNode.firstChild.nodeValue + this.sDelimChar;
		if(this.provider._caretPos && this.provider._caretPos.endText) {
			this.provider._caretPos.end = (oTextbox.value.length-(this.sDelimChar.length))-this.provider._caretPos.carriageReturns;
			oTextbox.value += this.provider._caretPos.endText.replace(this.sDelimChar, '');
		}
		if(this.sDelimChar != " " && this.sDelimChar != "\n") {
			oTextbox.value += " ";
		}
	} else {
		this.textbox.value = oNode.firstChild.nodeValue; 
	}
	
	//EDIT
	if (this.hidinput){ this.hidinput.value = oNode.id; }
	if (this.nextfunction) { try { eval(this.nextfunction); } catch (err) { } }
	
	// move cursor to end
	if(this.provider._caretPos && this.provider._caretPos.end) {
	    this.selectRange(this.provider._caretPos.end,this.provider._caretPos.end);
	} else {
		// scroll to bottom of textarea if necessary
	    if(oTextbox.type == "textarea") {
	        oTextbox.scrollTop = oTextbox.scrollHeight;
	    }
	
	    var end = oTextbox.value.length;
	    this.selectRange(end,end);
	}

	oTextbox.focus();
}


AutoSuggestControl.prototype.previousSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur > 0) {
        var oNode = cSuggestionNodes[--this.cur];
        this.highlightSuggestion(oNode);
        try { 
			this.setValue(oNode);
		}
		catch (err) {} // prev after first throws errors
    }
}

AutoSuggestControl.prototype.selectRange = function (iStart, iLength) {

    //use text ranges for Internet Explorer
    if (this.textbox.createTextRange) {
        var oRange = this.textbox.createTextRange(); 
		if(iStart == iLength) {
			oRange.collapse(true);
			oRange.moveEnd("character", iLength);
	        oRange.moveStart("character", iStart);
		}
		else {
			oRange.moveStart('character', iStart); 
			oRange.moveEnd('character', iLength - this.textbox.value.length);   
		}           
        oRange.select();

    //use setSelectionRange() for Mozilla
    } else if (this.textbox.setSelectionRange) {
        this.textbox.setSelectionRange(iStart, iLength);
    }     

    //set focus back to the textbox
    this.textbox.focus();      
}

AutoSuggestControl.prototype.showSuggestions = function (aSuggestions) {
    
    var oDiv = null;
    this.layer.innerHTML = '';  //clear contents of the layer
    
    for (var i=0; i < aSuggestions.length; i++) {
        oDiv = document.createElement('div');
	// EDIT
	suggestionId = aSuggestions[i][0];
	oDiv.setAttribute('id', suggestionId);
        //oDiv.appendChild(document.createTextNode(aSuggestions[i][1]));
		oDiv.innerHTML = aSuggestions[i][1];
        this.layer.appendChild(oDiv);
    }
    
    this.layer.style.left = this.getLeft() + 'px';
    this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + 'px';
    this.layer.style.display = 'block';

}

AutoSuggestControl.prototype.typeAhead = function (sSuggestion) {

    //check for support of typeahead functionality
    if (this.textbox.createTextRange || this.textbox.setSelectionRange){
        var iLen = this.textbox.value.length; 
        this.textbox.value = sSuggestion; 
        this.selectRange(iLen, sSuggestion.length);
    }
}

AutoSuggestControl.prototype._getCaretPosition = function(oTextbox) {
	var caretPos = 0;
 	// IE Support
 	if (document.selection) {
 		oTextbox.focus();
 		var bookmark = "\001";
 		var sel = document.selection.createRange();
		var dul = sel.duplicate();
		if(oTextbox.type == "textarea") {
	 		dul.moveToElementText(oTextbox);
			sel.text = bookmark;
	 		caretPos = dul.text.indexOf(bookmark);
	 		sel.moveStart('character', -1);
	 		sel.text = "";
		}
		else {
			dul.moveStart ('character', -oTextbox.value.length);
			caretPos = dul.text.length;
		}
 	}
 	// Firefox support
 	else if (oTextbox.selectionStart || oTextbox.selectionStart == '0')
 		caretPos = oTextbox.selectionStart;
 
 	return caretPos;
};

// edit after this point

function RemoteSuggestions() {
	this.http = createRequestObject();
	this.sURL = arguments[0];
	this.cachedSuggestions = {};
	this.numCachedSuggestions = 0;
}

RemoteSuggestions.prototype.requestSuggestions = function (sQuery, oAutoSuggestControl, bTypeAhead) {
    var oHttp = this.http;
    var oThis = this;
	
	sDelimChar = oAutoSuggestControl.sDelimChar;
	oTextbox = oAutoSuggestControl.textbox;
	this._caretPos = {pos: oAutoSuggestControl._getCaretPosition(oTextbox)};
	
	// reset the hidden input, only way to gurantee the user selects an option
	oAutoSuggestControl.hidinput.value = '0';
	
   	if(this.bMultipleItems && this._caretPos.pos && this._caretPos.pos != -1 && oTextbox.value.length != this._caretPos.pos) {
   		this._caretPos.end = sQuery.indexOf(sDelimChar, this._caretPos.pos);
   		this._caretPos.endText = sQuery.substr(this._caretPos.end);
   		var newQuery = sQuery.substr(0, this._caretPos.end);
   		this._caretPos.start = newQuery.lastIndexOf(sDelimChar)+1;
   	
   		this._caretPos.carriageReturns = 0;
   		while(newQuery.indexOf("\r") != -1) {
   			newQuery = newQuery.replace("\r", '');
   			this._caretPos.carriageReturns++;
   		}
   	
   		sQuery = newQuery;
   	}

   	var nDelimIndex = sQuery.lastIndexOf(sDelimChar);
   	if(nDelimIndex > -1) {
   		var nQueryStart = nDelimIndex + 1;
   		// Trim any white space from the beginning...
   		while(sQuery.charAt(nQueryStart) == " ") {
   			nQueryStart += 1;
   		}
   		// ...and save the rest of the string for later
   		this._caretPos.startText = sQuery.substring(0,nQueryStart);
   		// Here is the query itself
   		sQuery = sQuery.substr(nQueryStart);
   	}
   
	var cQuery = trim(sQuery).replace("\n", '');
   	sQuery = encodeURIComponent(sQuery);
   	var sURL = (oAutoSuggestControl.bMultipleItems)?eval(this.sURL)+cQuery:eval(this.sURL);
   	//console.log(sQuery);
   	//console.log(this._caretPos.pos, this._caretPos.end, this._caretPos.endText, this._caretPos.start, this._caretPos.startText);

	if(cQuery.length < 3) {
		oAutoSuggestControl.hideSuggestions();
		return;
	}
	
	//if there is already a live request, cancel it
    if (oHttp.readyState != 0) { oHttp.abort(); }

	// check if the subset query is cached, if so, send that as suggestions
   	var fSug = []; var tmp = null; var fReg = new RegExp(decodeURIComponent(cQuery), "gi");
	for(cachedQuery in oThis.cachedSuggestions) {
		if(cQuery.indexOf(cachedQuery) == 0) {
			// FIX FIX FIX, pick out new matches and send
			for (var i=0; i<oThis.cachedSuggestions[cachedQuery].length; i++) {
				tmp = oThis.cachedSuggestions[cachedQuery][i];
            	if (tmp[1].match(fReg) != null) { fSug[fSug.length] = [tmp[0], tmp[1]]; }
			}
			oAutoSuggestControl.autosuggest(fSug);
			return;
		} else if(oThis.numCachedSuggestions > 5) {
			delete(oThis.cachedSuggestions[cachedQuery]);
		}
	}

    //open connection to states.txt file
    oHttp.open("get", sURL , true);
    oHttp.onreadystatechange = function () {
        if (oHttp.readyState == 4) {
            // check briefly what we are getting back has a ] at the end
            returnString = oHttp.responseText;
            reg = /\]$/;
            if (returnString.length > 1 && reg.test(returnString)) {
                //evaluate the returned text JavaScript (an array)
                var aSuggestions = eval(returnString);
				oThis.cachedSuggestions[cQuery] = aSuggestions;
				oThis.numCachedSuggestions++;
                //provide suggestions to the control
                oAutoSuggestControl.autosuggest(aSuggestions);
				
            } else {
                return false;
            }
        }
    }
    oHttp.send(null);
}
function AutoSuggestControl() {
    
    this.cur = -1;
    this.layer = null;
	this.provider = arguments[0];

	// require the textboxid
	if (arguments[1]['textboxid']) { this.textbox = getEl(arguments[1]['textboxid']); }
	else { alert('Textbox id not specified.'); return false; }

	// check for hidden id
	this.hidinput = (arguments[1]['hiddenid'])?getEl(arguments[1]['hiddenid']):false;

	// check for nextfunction (calls another function when a value is selected)
	this.nextfunction = (arguments[1]['nextfunction'])?arguments[1]['nextfunction']:false;
	
	if(arguments[1]['delimeter'] && arguments[1]['delimeter'].length) {
		this.bMultipleItems = true;
		this.sDelimChar = arguments[1]['delimeter'];
	} else {
		this.bMultipleItems = false;
	}

    this.init();
}

AutoSuggestControl.prototype.autosuggest = function (aSuggestions, bTypeAhead) {
    if (aSuggestions.length > 0) {
        if (bTypeAhead) { this.typeAhead(aSuggestions[0][1]); }
        this.showSuggestions(aSuggestions);
    } else {
        this.hideSuggestions();
    }
}

AutoSuggestControl.prototype.createDropDown = function () {
    var oThis = this;
	var oNode = this.textbox;

    //create the layer and assign styles
    this.layer = document.createElement('div');
    this.layer.className = 'suggestions';
    this.layer.style.display = 'none';

    this.layer.onmouseover = 
    this.layer.onmouseup = 
    this.layer.onmousedown = function (oEvent) {
        oEvent = oEvent || window.event;
        oTarget = oEvent.target || oEvent.srcElement;
   	    if (oEvent.type == 'mouseover') { oThis.highlightSuggestion(oTarget); }
   	    if (oEvent.type == 'mousedown') { oThis.setValue(oTarget); }
   	}
    
    document.body.appendChild(this.layer);
}

AutoSuggestControl.prototype.getLeft = function () {

    var oNode = this.textbox;
    var iLeft = 0;
    
    while(oNode.tagName != 'BODY') {
        iLeft += oNode.offsetLeft;
        oNode = oNode.offsetParent;        
    }
    
    return iLeft;
}

AutoSuggestControl.prototype.getTop = function () {

    var oNode = this.textbox;
    var iTop = 0;
    
    while(oNode.tagName != 'BODY') {
        iTop += oNode.offsetTop;
        oNode = oNode.offsetParent;
    }
    
    return iTop;
}

AutoSuggestControl.prototype.handleKeyDown = function (oEvent) {
    switch(oEvent.keyCode) {
        case 38: //up arrow
            this.previousSuggestion();
            break;
        case 40: //down arrow 
            this.nextSuggestion();
            break;
        case 13: //enter
            this.hideSuggestions();
			try { eval(this.nextfunction); }
			catch (err) { }
            break;
    }
}

AutoSuggestControl.prototype.handleKeyUp = function (oEvent) {
    var iKeyCode = oEvent.keyCode;

    //for backspace (8) and delete (46), shows suggestions without typeahead
    if (iKeyCode == 8 || iKeyCode == 46) {
        this.provider.requestSuggestions(this.textbox.value, this, false);
        
    //make sure not to interfere with non-character keys
    } else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123)) {
        //ignore
    } else {
        //request suggestions from the suggestion provider with typeahead
        this.provider.requestSuggestions(this.textbox.value, this, true);
    }
}

AutoSuggestControl.prototype.hideSuggestions = function () {
    this.layer.style.display = 'none';
	this.layer.innerHTML = '';
	this.cur = -1;
//	this.textbox.focus();
}

AutoSuggestControl.prototype.highlightSuggestion = function (oSuggestionNode) {
    
    for (var i=0; i < this.layer.childNodes.length; i++) {
        var oNode = this.layer.childNodes[i];
        if (oNode == oSuggestionNode) {
            oNode.className = 'current'
        } else if (oNode.className == 'current') {
            oNode.className = '';
        }
    }
}

AutoSuggestControl.prototype.init = function () {
    //save a reference to this object
    var oThis = this;
    
    //assign the onkeyup event handler
    this.textbox.onkeyup = function (oEvent) {
    
        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }    
        
        //call the handleKeyUp() method with the event object
        oThis.handleKeyUp(oEvent);
    }
    
    //assign onkeydown event handler
    this.textbox.onkeydown = function (oEvent) {
    
        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }    
        
        //call the handleKeyDown() method with the event object
        oThis.handleKeyDown(oEvent);
    }

    //assign onblur event handler (hides suggestions)    
    this.textbox.onblur = function () {
        oThis.hideSuggestions();
    }

    //create the suggestions dropdown
    this.createDropDown();
}

AutoSuggestControl.prototype.nextSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) {
        var oNode = cSuggestionNodes[++this.cur];
        this.highlightSuggestion(oNode);

		this.setValue(oNode);
    }
}

AutoSuggestControl.prototype.setValue = function (oNode) {
	var oTextbox = this.textbox;
	if(this.bMultipleItems && this.sDelimChar) {
		//if(this.provider._caretPos.startText) {
			oTextbox.value = this.provider._caretPos.startText || '';
		//}
		//console.log(this.provider._caretPos.startText, oTextbox.value);
		oTextbox.value += oNode.firstChild.nodeValue + this.sDelimChar;
		if(this.provider._caretPos && this.provider._caretPos.endText) {
			this.provider._caretPos.end = (oTextbox.value.length-(this.sDelimChar.length))-this.provider._caretPos.carriageReturns;
			oTextbox.value += this.provider._caretPos.endText.replace(this.sDelimChar, '');
		}
		if(this.sDelimChar != " " && this.sDelimChar != "\n") {
			oTextbox.value += " ";
		}
	} else {
		this.textbox.value = oNode.firstChild.nodeValue; 
	}
	
	//EDIT
	if (this.hidinput){ this.hidinput.value = oNode.id; }
	if (this.nextfunction) { try { eval(this.nextfunction); } catch (err) { } }
	
	// move cursor to end
	if(this.provider._caretPos && this.provider._caretPos.end) {
	    this.selectRange(this.provider._caretPos.end,this.provider._caretPos.end);
	} else {
		// scroll to bottom of textarea if necessary
	    if(oTextbox.type == "textarea") {
	        oTextbox.scrollTop = oTextbox.scrollHeight;
	    }
	
	    var end = oTextbox.value.length;
	    this.selectRange(end,end);
	}

	oTextbox.focus();
}


AutoSuggestControl.prototype.previousSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur > 0) {
        var oNode = cSuggestionNodes[--this.cur];
        this.highlightSuggestion(oNode);
        try { 
			this.setValue(oNode);
		}
		catch (err) {} // prev after first throws errors
    }
}

AutoSuggestControl.prototype.selectRange = function (iStart, iLength) {

    //use text ranges for Internet Explorer
    if (this.textbox.createTextRange) {
        var oRange = this.textbox.createTextRange(); 
		if(iStart == iLength) {
			oRange.collapse(true);
			oRange.moveEnd("character", iLength);
	        oRange.moveStart("character", iStart);
		}
		else {
			oRange.moveStart('character', iStart); 
			oRange.moveEnd('character', iLength - this.textbox.value.length);   
		}           
        oRange.select();

    //use setSelectionRange() for Mozilla
    } else if (this.textbox.setSelectionRange) {
        this.textbox.setSelectionRange(iStart, iLength);
    }     

    //set focus back to the textbox
    this.textbox.focus();      
}

AutoSuggestControl.prototype.showSuggestions = function (aSuggestions) {
    
    var oDiv = null;
    this.layer.innerHTML = '';  //clear contents of the layer
    
    for (var i=0; i < aSuggestions.length; i++) {
        oDiv = document.createElement('div');
	// EDIT
	suggestionId = aSuggestions[i][0];
	oDiv.setAttribute('id', suggestionId);
        //oDiv.appendChild(document.createTextNode(aSuggestions[i][1]));
		oDiv.innerHTML = aSuggestions[i][1];
        this.layer.appendChild(oDiv);
    }
    
    this.layer.style.left = this.getLeft() + 'px';
    this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + 'px';
    this.layer.style.display = 'block';

}

AutoSuggestControl.prototype.typeAhead = function (sSuggestion) {

    //check for support of typeahead functionality
    if (this.textbox.createTextRange || this.textbox.setSelectionRange){
        var iLen = this.textbox.value.length; 
        this.textbox.value = sSuggestion; 
        this.selectRange(iLen, sSuggestion.length);
    }
}

AutoSuggestControl.prototype._getCaretPosition = function(oTextbox) {
	var caretPos = 0;
 	// IE Support
 	if (document.selection) {
 		oTextbox.focus();
 		var bookmark = "\001";
 		var sel = document.selection.createRange();
		var dul = sel.duplicate();
		if(oTextbox.type == "textarea") {
	 		dul.moveToElementText(oTextbox);
			sel.text = bookmark;
	 		caretPos = dul.text.indexOf(bookmark);
	 		sel.moveStart('character', -1);
	 		sel.text = "";
		}
		else {
			dul.moveStart ('character', -oTextbox.value.length);
			caretPos = dul.text.length;
		}
 	}
 	// Firefox support
 	else if (oTextbox.selectionStart || oTextbox.selectionStart == '0')
 		caretPos = oTextbox.selectionStart;
 
 	return caretPos;
};

// edit after this point

function RemoteSuggestions() {
	this.http = createRequestObject();
	this.sURL = arguments[0];
	this.cachedSuggestions = {};
	this.numCachedSuggestions = 0;
}

RemoteSuggestions.prototype.requestSuggestions = function (sQuery, oAutoSuggestControl, bTypeAhead) {
    var oHttp = this.http;
    var oThis = this;
	
	sDelimChar = oAutoSuggestControl.sDelimChar;
	oTextbox = oAutoSuggestControl.textbox;
	this._caretPos = {pos: oAutoSuggestControl._getCaretPosition(oTextbox)};
	
	// reset the hidden input, only way to gurantee the user selects an option
	oAutoSuggestControl.hidinput.value = '0';
	
   	if(this.bMultipleItems && this._caretPos.pos && this._caretPos.pos != -1 && oTextbox.value.length != this._caretPos.pos) {
   		this._caretPos.end = sQuery.indexOf(sDelimChar, this._caretPos.pos);
   		this._caretPos.endText = sQuery.substr(this._caretPos.end);
   		var newQuery = sQuery.substr(0, this._caretPos.end);
   		this._caretPos.start = newQuery.lastIndexOf(sDelimChar)+1;
   	
   		this._caretPos.carriageReturns = 0;
   		while(newQuery.indexOf("\r") != -1) {
   			newQuery = newQuery.replace("\r", '');
   			this._caretPos.carriageReturns++;
   		}
   	
   		sQuery = newQuery;
   	}

   	var nDelimIndex = sQuery.lastIndexOf(sDelimChar);
   	if(nDelimIndex > -1) {
   		var nQueryStart = nDelimIndex + 1;
   		// Trim any white space from the beginning...
   		while(sQuery.charAt(nQueryStart) == " ") {
   			nQueryStart += 1;
   		}
   		// ...and save the rest of the string for later
   		this._caretPos.startText = sQuery.substring(0,nQueryStart);
   		// Here is the query itself
   		sQuery = sQuery.substr(nQueryStart);
   	}
   
   	sQuery = encodeURIComponent(sQuery);
   	var sURL = (oAutoSuggestControl.bMultipleItems)?eval(this.sURL)+sQuery:eval(this.sURL);
   	//console.log(sQuery);
   	//console.log(this._caretPos.pos, this._caretPos.end, this._caretPos.endText, this._caretPos.start, this._caretPos.startText);

	if(sQuery.length < 3) {
		oAutoSuggestControl.hideSuggestions();
		return;
	}
	
	//if there is already a live request, cancel it
    if (oHttp.readyState != 0) { oHttp.abort(); }

	// check if the subset query is cached, if so, send that as suggestions
   	var fSug = []; var tmp = null; var fReg = new RegExp(decodeURIComponent(sQuery), "gi");
	for(cachedQuery in oThis.cachedSuggestions) {
		if(sQuery.indexOf(cachedQuery) == 0) {
			// FIX FIX FIX, pick out new matches and send
			for (var i=0; i<oThis.cachedSuggestions[cachedQuery].length; i++) {
				tmp = oThis.cachedSuggestions[cachedQuery][i];
            	if (tmp[1].match(fReg) != null) { fSug[fSug.length] = [tmp[0], tmp[1]]; }
			}
			oAutoSuggestControl.autosuggest(fSug);
			return;
		} else if(oThis.numCachedSuggestions > 5) {
			delete(oThis.cachedSuggestions[cachedQuery]);
		}
	}

    //open connection to states.txt file
    oHttp.open("get", sURL , true);
    oHttp.onreadystatechange = function () {
        if (oHttp.readyState == 4) {
            // check briefly what we are getting back has a ] at the end
            returnString = oHttp.responseText;
            reg = /\]$/;
            if (returnString.length > 1 && reg.test(returnString)) {
                //evaluate the returned text JavaScript (an array)
                var aSuggestions = eval(returnString);
				oThis.cachedSuggestions[sQuery] = aSuggestions;
				oThis.numCachedSuggestions++;
                //provide suggestions to the control
                oAutoSuggestControl.autosuggest(aSuggestions);
				
            } else {
                return false;
            }
        }
    }
    oHttp.send(null);
}
// called when the user focuses on a date field
function calShow(e) {
	// verify info
	var calInput = findTarget(e, 'input', 'caltype');
	if (!calInput && checkAttr(e, 'caltype')) { calInput = e; }
	if (!calInput) { alert('Date field not found.'); return false; }

	var calType = calInput.getAttribute('caltype');
	var calHid = (checkAttr(calInput, 'calhid'))?getEl(calInput.getAttribute('calhid')):false;
	var theDate = (checkAttr(calInput, 'fulldate'))?calStr2Obj(calInput.getAttribute('fulldate'), calType):(calHid)?calStr2Obj(calHid.value, calType):false;
	if (!theDate) { theDate = new Date(); theDate.setMinutes(0, 0); }

	// create cal div if needed	
	var calDiv = getEl('caldiv');
	if (!calDiv) {
		calDiv = newEl({"type":"div","class":"iframe","id":"caldiv","style":{"top":"10px", "left":"10px"}}, document.body);
		calDiv.onmouseover = function(e) { getEl('caldiv').setAttribute('mouseover', '1'); }
		calDiv.onmouseout = function(e) { getEl('caldiv').removeAttribute('mouseover'); }
	}

	// (re)set the calinput
	calDiv.datefield = calInput;
   	calDiv.setAttribute('caltype', calType);

	calWrite(theDate);
	calDiv.input = calInput;

	// show it
	bringElementHere(e, getEl('caldiv'));
	calInput.onblur = calBlur;
}

// converts a fulldate "2008-04-13 9:00:00" OR "2008-04-13" to a date object
function calStr2Obj(str, type) {
	if (type == 'date') { 
    	var datereg = /([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/;
	    if (!datereg.test(str)) { return new Date(); }
    	var ar = datereg.exec(str);
    	return new Date(parseInt(ar[1], 10), parseInt(ar[2], 10) -1, parseInt(ar[3], 10));
	} else if (type == 'datetime') {
    	var datereg = /([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})/;
	    if (!datereg.test(str)) { var dt = new Date(); dt.setMinutes(0, 0); return dt; }
    	var ar = datereg.exec(str);
    	return new Date(parseInt(ar[1], 10), parseInt(ar[2], 10) -1, parseInt(ar[3], 10), parseInt(ar[4], 10), parseInt(ar[5], 10), parseInt(ar[6], 10));
	}
}

// creates the cal table inside the div
function calWrite(dateObj) {
	var calDiv = getEl('caldiv');
	if (!calDiv) { alert('Error: calendar container not found.'); return false; }
	calDiv.innerHTML = '';
	calTable = false;
	calType = calDiv.getAttribute('caltype');

	if (calType == 'date' || calType == 'datetime') {
		var thismonth = dateObj.getMonth();
		var thisyear = dateObj.getFullYear();
		var thisdate = dateObj.getDate();
		calDiv.setAttribute('year', thisyear);
		calDiv.setAttribute('month', thismonth);
		calDiv.setAttribute('date', thisdate);
	

	    // define week and month arrays
	    var weekdays = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat", "Sun");
	    var allmonths = new Array("January","February","March","April","May","June","July","August","September","October","November","December");

		// the table
		var calTable = newEl({"type":"table","class":"forms sfont","attributes":{"cellspacing":2}});
		calTable = newEl({"type":"tbody"}, calTable);

		// title row
		var row = newEl({"type":"tr", "class":"head"}, calTable);
		var cell = newEl({"type":"td","attributes":{"colspan":7,"align":"center"}}, row);

		// month
		newEl({"type":"span", "class":"fakelink xxlfont tnrf", "text":"\u2039", "onclick":"calChange", "attributes":{"month":thismonth-1}}, cell);
		newEl({"type":"span","class":"hspace10","text":allmonths[thismonth]}, cell);
		newEl({"type":"span", "class":"fakelink xxlfont rspace20 tnrf", "text":"\u203A", "onclick":"calChange", "attributes":{"month":thismonth+1}}, cell);

		// year
		newEl({"type":"span", "class":"fakelink xxlfont tnrf", "text":"\u2039", "onclick":"calChange", "attributes":{"year":thisyear-1}}, cell);
		newEl({"type":"span","class":"hspace10","text":thisyear.toString()}, cell);
		newEl({"type":"span", "class":"fakelink xxlfont tnrf", "text":"\u203A", "onclick":"calChange", "attributes":{"year":thisyear+1}}, cell);

		// weekdays row
		row = newEl({"type":"tr"}, calTable);
		for (var i=1; i < weekdays.length; i++) { newEl({"type":"td","class":"light alignc", "text":weekdays[i]}, row); }

		// cal days
		row = newEl({"type":"tr","attributes":{"isweek":"1"}}, calTable);

		// set start and end dates
		var startDate = new Date(thisyear, thismonth, 1);
		var endDate = new Date(thisyear, thismonth +1, 1); 

		// reset the start and end dates to be beginning and end of the week
		if (startDate.getDay() != 1) {
			var numDaysBack = (startDate.getDay() == 0)?6:startDate.getDay() - 1;
			startDate.setDate(startDate.getDate() - numDaysBack);
		}
		// set enddate to the sunday
		endDate.setDate(endDate.getDate() -1);
		if (endDate.getDay() != 0) {
			var numDaysForw = 7 - endDate.getDay();
			endDate.setDate(endDate.getDate() + numDaysForw);
		}
		
		var year = null; var month = null; var date = null;
		while (startDate <= endDate) {
			date = startDate.getDate().toString();
			month = startDate.getMonth().toString();
			year = startDate.getFullYear().toString();
	
			// create a cell foreach day
			cell = newEl({"type":"td","class":"cal","text":date,"onclick":"calSelectDate","attributes":{"align":"center", "width":27, "date":date, "month":month, "year":year}}, row);
	
			// add attrs if this is the month
			if (month == thismonth) {
				cell.setAttribute("id", 'cal_date_'+date);
				cell.className = cell.className = ' calmonth'; 
			}
	
			// mark the selected date
			if (date == thisdate && month == thismonth) { cell.className = cell.className + ' calsel'; }
	
			// increment the date
			startDate.setDate(startDate.getDate() + 1);
	
			// create a new row for another week
			if (startDate.getDay() == 1 && startDate <= endDate) { row = newEl({"type":"tr","attributes":{"isweek":"1"}}, calTable); }
		}
	}

	if (calType == 'time' || calType == 'datetime') {
		// make sure that we have a table
		if (!calTable) {
			var calTable = newEl({"type":"table","class":"forms","attributes":{"cellspacing":2}}, calDiv);
			calTable = newEl({"type":"tbody"}, calTable);
		}

		var thishour = dateObj.getHours();
		var thismin = dateObj.getMinutes();
		if (thismin < 10) { thismin = '0'+ thismin; }
		var thisapm = (thishour > 12)?'PM':'AM'
		if (thisapm == 'PM') { thishour -= 12; }

		calDiv.setAttribute('hour', thishour);
		calDiv.setAttribute('min', thismin);
		calDiv.setAttribute('apm', thisapm);

		row = newEl({"type":"tr"}, calTable);
		cell = newEl({"type":"td","attributes":{"colspan":"7","align":"center"}}, row); 

		newEl({"type":"input","class":"textl alignr","onfocus":"focusSelectAll","attributes":{"type":"text","id":"cal_hour","size":"1","value":thishour}}, cell).onkeyup = calCheckAPM;
		newEl({"type":"span", "class":"forms", "text":":"}, cell);
		newEl({"type":"input","class":"textl","onfocus":"focusSelectAll","attributes":{"type":"text","id":"cal_min","size":"1","value":thismin}}, cell);
		var am = newEl({"type":"span","class":"lspace10 a","text":"AM","onclick":calChooseAPM,"attributes":{"id":"cal_am","apm":"am","ismarked":0}}, cell);
		var pm = newEl({"type":"span","class":"lspace10 a","text":"PM","onclick":calChooseAPM,"attributes":{"id":"cal_pm","apm":"pm","ismarked":0}}, cell);
		if (thisapm == 'PM') { pm.setAttribute('ismarked', '1'); pm.className += ' bright'; } else { am.setAttribute('ismarked', '1'); am.className += ' bright'; }

		/*
		var tzoffset = parseFloat(new Date().getTimezoneOffset()/60);
		var tz = (tzoffset > 0)?'UTC -'+ tzoffset:'UTC +'+ tzoffset;
		*/
		tz = 'EST';
		newEl({"type":"span","class":"lspace10 thick dark","text":tz}, cell);
	} // end time

   	// submit cancel links
   	row = newEl({"type":"tr"}, calTable);
   	cell = newEl({"type":"td", "class":"alignc", "attributes":{"colspan":7}}, row);
   	newEl({"type":"input", "class":"buttonl", "onclick":"calSubmit", "attributes":{"type":"button", "value":"Submit"}}, cell);
	newEl({"type":"span", "class":"hsep", "text":"|"}, cell);
   	newEl({"type":"input", "class":"buttonl", "onclick":"calHide", "attributes":{"type":"button", "value":"Cancel"}}, cell);

	calDiv.appendChild(calTable.parentNode);
}

// new month or year is selected
function calChange(e) {
	var theLink = findTarget(e, 'span');
	if (!theLink) { return false; }

	var calDiv = getEl('caldiv');
	var year, month;

	if (checkAttr(theLink, 'year')) {
		year = theLink.getAttribute('year');
		month =  calDiv.getAttribute('month');
	} else {
		year = calDiv.getAttribute('year');
		month =  theLink.getAttribute('month');
	}

	var date = calDiv.getAttribute('date');
	if (month < 0) { month = 11; year--; }
	if (month > 11) { month = 1; year++; }
	var dateObj = new Date(year, month, date);

	// get the time if needed
	if (checkAttr(calDiv, 'hour')) { dateObj.setHours(calDiv.getAttribute('hour'), calDiv.getAttribute('min')); }

	// check month (April 31 goes to May 1)
	if (dateObj.getMonth() != month) {
		dateObj.setDate(1);
    	dateObj.setMonth(parseInt(month, 10)+1);
		dateObj.setDate(dateObj.getDate() - 1);
	}

	calWrite(dateObj);
}

// selects date on click
function calSelectDate(e) {
	// make sure we have the cell
	var theCell = findTarget(e, 'td');
	if (!theCell) { alert('Error finding calendar date.'); return false; }

	// get some info
	var calDiv = getEl('caldiv');
	var prevdate = calDiv.getAttribute('date');
	var newdate = theCell.getAttribute('date');

	// check if the month needs to change
	if (calDiv.getAttribute('month') != theCell.getAttribute('month')) {
    	var dateObj = new Date();
		dateObj.setFullYear(theCell.getAttribute('year'));
		dateObj.setMonth(theCell.getAttribute('month'));
		dateObj.setDate(theCell.getAttribute('date'))

		calWrite (dateObj);
	}

	// change the class
	getEl('cal_date_'+ prevdate).className = getEl('cal_date_'+ prevdate).className.replace(/calsel/g, '');
	getEl('cal_date_'+ newdate).className = getEl('cal_date_'+ newdate).className + ' calsel';

	// update the row
	calDiv.setAttribute('date', newdate);

	// focus on the hour if exists
	if (getEl('cal_hour')) { getEl('cal_hour').select(); } else { calSubmit(); }
}

// submits
function calSubmit() {
	var calDiv = getEl('caldiv');
	var calInput = calDiv.input;
	var calType = (checkAttr(calInput, 'caltype'))?calInput.getAttribute('caltype'):'date';
	var calHid = (checkAttr(calInput, 'calhid'))?getEl(calInput.getAttribute('calhid')):false;

	var format_strings = ['%m/%d/%y', '%Y-%m-%d', ' %I:%M %p', ' %H:%M:00'];
	var td = new Date();
	if (td.format('#YY#').indexOf('#') == -1) {
		format_strings = ['#MM#/#DD#/#YY#', '#YYYY#-#MM#-#DD#', ' #h#:#mm# #ampm#', ' #hhh#:#mm#:00'];
	}

	/*
	try {
		//if (JSON.encode(format_strings).length > 0) {
		if (new Date.intest() == 48) {
			var format_strings = ['#MM#/#DD#/#YY#', '#YYYY#-#MM#-#DD#', ' #h#:#mm# #ampm#', ' #hhh#:#mm#:00'];
			format_strings = ['%m/%d/%y', '%Y-%m-%d', ' %I:%M %p', ' %H:%M:00'];
		}
	} catch (err) {}
	*/

	var viewdate = ''; var fulldate = '';

	var dateObj = new Date();
	if (calType == 'date' || calType == 'datetime') {
		dateObj.setFullYear(calDiv.getAttribute('year'), calDiv.getAttribute('month'), calDiv.getAttribute('date'));
		viewdate += dateObj.format(format_strings[0]);
		fulldate += dateObj.format(format_strings[1]);
	}
	if (calType == 'time' || calType == 'datetime') {
		var hour = parseInt(getEl('cal_hour').value, 10);
		if (calDiv.getAttribute('apm') == 'PM' && hour < 12) { hour = hour +12; }
		dateObj.setHours(hour, getEl('cal_min').value, '0');
		viewdate += dateObj.format(format_strings[2]);
		fulldate += dateObj.format(format_strings[3]);
	}

	calInput.value = trim(viewdate);

	// check if we need to set the attribute
    if (calHid) { calHid.value = fulldate; } else { calInput.setAttribute('fulldate', fulldate); }

	// check if we need to run an update function
	if (checkAttr(calInput, 'onsave')) { window[calInput.getAttribute('onsave')](calInput); }

	calHide();	
}

function calBlur(e) {
	if (checkAttr(getEl('caldiv'), 'mouseover')) { return false; }
	calHide(e);
}

// hides cal
function calHide(e) {
	getEl('caldiv').style.visibility = 'hidden';
	getEl('caldiv').style.display = 'none';
	getEl('caldiv').input.onblur = null;
}

// checks the hour to preset am pm
function calCheckAPM(e) {
	var hour = findTarget(e, 'input')
	if (!hour) { return false; }

	hour = parseInt(hour.value, 10);
	if (hour > 7 && hour < 12) { calChooseAPM('AM'); }
	else { calChooseAPM('PM'); }
}

// selects am or pm
function calChooseAPM(e) {
	// find am or pm
	if (!inArray(e, ['AM', 'PM'])) {
		var apm = findTarget(e, 'span', 'apm');
		if (!apm) { alert('Error, am or pm not specified.'); }
		e = apm.getAttribute('apm').toUpperCase();
	}

	var links = {'AM':getEl('cal_am'), 'PM':getEl('cal_pm')};

	// reset both
	for (l in links) {
		links[l].className = links[l].className.replace(/ bright/, '');
		links[l].setAttribute('ismarked', 0);
	}

	links[e].className += ' bright';
   	links[e].setAttribute('ismarked', 1);
	getEl('caldiv').setAttribute('apm', e);
}
function findTarget() {
	var e = arguments[0];
	var nodeType = arguments[1];

	var target = false;
	// the try statements are for broken IE
	if (window.event && window.event.srcElement) {
		try { target = window.event.srcElement; }
		catch (err) { alert('window.event '+ err.description); }
	} else {
		try { target = e.target; }
		catch (err) { alert('target error:'+ err.description); }
	}

	if (!target || !target.nodeName) { return false; }
	if (target.nodeName == '#document') { return false; }

	while (target != document.body && target.nodeName.toLowerCase() != nodeType) {
		target = target.parentNode;
	}

	if (target == document.body) { return false; }

	// check for the attribute if needed
	if (arguments.length > 2 && !checkAttr(target, arguments[2])) {
   		target = target.parentNode;
		while (true) {
			if (target == document.body) { return null; }
			if (target.nodeName.toLowerCase() == nodeType && checkAttr(target, arguments[2])) { return target; }
   			target = target.parentNode;
		}
	}

	if (target.nodeName.toLowerCase() != nodeType) { return null; }
	return target;
}

function findParent() {
	var obj = arguments[0];
	var nodeType = arguments[1];

	if (!obj) { return false; }

	while (obj != document.body && obj.nodeName.toLowerCase() != nodeType) {
		obj = obj.parentNode;
	}

	// check for the attribute if needed
	if (arguments.length > 2 && !checkAttr(obj, arguments[2])) {
   		obj = obj.parentNode;
		while (true) {
			if (obj == document.body) { return false; }
			if (obj.nodeName.toLowerCase() == nodeType && checkAttr(obj, arguments[2])) { return obj; }
   			obj = obj.parentNode;
		}
	}

	if (obj.nodeName.toLowerCase() != nodeType) { return false; }
	return obj;
}

function findChild() {
	var obj = arguments[0];
	var nodeType = arguments[1];

	if (!obj) { return false; }

	for (var i=0; i<obj.childNodes.length; i++) {
		// compare type
		if (obj.childNodes[i].nodeName.toLowerCase() == nodeType) {
			// check for the attribute if needed
			if (arguments.length > 2) {
				if (!checkAttr(obj.childNodes[i], arguments[2])) { continue; }
			}
			return obj.childNodes[i];
		}
	}

	return false;
}

function findiFrame() {
	// make sure that we are in a frame
	if (parent.document == document) { alert('Not in iframe.'); return false; }

	var iFs = parent.document.getElementsByTagName('iframe');
	if (iFs.length == 0) { alert('No iframes found.'); return false; }

	for (var i=0; i<iFs.length; i++) {
		if (iFs[i].src == location.href || location.href.indexOf(iFs[i].src) != -1) { return iFs[i]; }
	}

	return false;
}

function isSet(varname)  {
	if(typeof(varname) != "undefined") return true;
	else return false;
}

function inArray(needle, haystack) {
	for (var h in haystack) {
		if (haystack[h] == needle) { return true; }
	}
	return false;
}

function commonInArray(ar1, ar2) {
	for (var i=0; i<ar1.length; i++) {
		if (inArray(ar1[i], ar2)) { return true; }
	}
	return false;
}

function readableSize(size) {
	var i=0;
	size = parseInt(size, 10);
	var iec = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
	while ((size/1024)>1) {
		size=size/1024;
		i++;
	}

	size = Math.round(size*100)/100;
	size = addCommas(size);
	return size+ ' ' +iec[i];
}

function strpos(str, ch) {
	for (var i = 0; i < str.length; i++)
	if (str.substring(i, i+1) == ch) return i;
	return -1;
}

function trim(stringToTrim) {
	if (typeof(stringToTrim) != "string") { return stringToTrim; }
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}

// get the mouse position on the page
function getMousePos(ev){
	if(ev.pageX || ev.pageY){
		return {x:ev.pageX, y:ev.pageY};
	}
	return {
		x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
		y:ev.clientY + document.body.scrollTop - document.body.clientTop
	};
}

function checkEnter(e, submitFunction) {
	if (!e) { e = event; }
	pK = (e.which)?e.which:e.keyCode;
	if (pK == 13) { eval(submitFunction); return false; }
	return pK != 13;
}

function createRequestObject() {
	if (typeof XMLHttpRequest != "undefined") {
		ohttp = new XMLHttpRequest();
	} else if (typeof ActiveXObject != "undefined") {
		ohttp = new ActiveXObject("MSXML2.XmlHttp");
	} else {
		alert("No XMLHttpRequest object available. This functionality will not work.");
	}
	return ohttp;
}

function getAjaxInfo() {
	// set reqruirements
	if (!arguments[0]["url"]) { alert('Could not find the service URL. Please contact the admin.'); return false; }
	//if (!arguments[0]["handler"]) { alert('Could not find the response handler. Please contact the admin.'); return false; }

	var sURL = arguments[0]["url"];
	var responseFunction = arguments[0]["handler"] || 'showAjaxResponse';
	var xArgs = (arguments[0]['args'])?arguments[0]['args']:false;
	var gReqObj = null;
	if (arguments[0]['gHttp']) { gReqObj = arguments[0]['gHttp']; }
	else if (typeof(window['gHttp'])) { try { gReqObj = gHttp; } catch (err) { gReqObj = createRequestObject(); } }
	else { gReqObj = createRequestObject(); }

	if (gReqObj.readyState != 0) { gReqObj.abort(); }
	//open connection
	gReqObj.open("get", sURL , true);
	// show Loading
	setTransfer(true);

	gReqObj.onreadystatechange = function () {
		if (gReqObj.readyState == 4) {
			// hide Loading
			setTransfer(false);
			aInfo = eval(gReqObj.responseText);
			if (aInfo[0]['action'] && aInfo[0]['action'] == 'reauthenticate') { reauthUser('start'); return false; }
			if (xArgs) {
				eval(responseFunction+ "(aInfo[0], xArgs)");
			} else {
				eval(responseFunction+ "(aInfo[0])");
			}
		}
	} // end function handleResponse
	gReqObj.send(null);
}

function postAjaxInfo() {
	// set reqruirements
	if (!arguments[0]["url"]) { alert('Could not find the service URL. Please contact the admin.'); return false; }
	if (!arguments[0]['theData']) { alert('Could not find the data to send. Please contact the admin.'); return false; }
	if (!arguments[0]["handler"]) { alert('Could not find the response handler. Please contact the admin.'); return false; }

	var sURL = arguments[0]["url"];
	var theData = arguments[0]['theData'];
	var responseFunction = arguments[0]["handler"];
	var xArgs = (arguments[0]['args'])?arguments[0]['args']:false;
	if (arguments[0]['pHttp']) { var pReqObj = arguments[0]['pHttp']; }
	else if (typeof(window['pHttp']) != "undefined") { var pReqObj = pHttp; }
	else { var pReqObj = createRequestObject(); }

	// if there is already a live request, cancel it
	if (pReqObj.readyState != 0)
		pReqObj.abort();
	// show Loading
	setTransfer(true);

	//open connection
	pReqObj.open('post', sURL, true);
	pReqObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	pReqObj.setRequestHeader("Content-length", theData.length);
	pReqObj.setRequestHeader("Connection", "close");
	pReqObj.send(theData);
	pReqObj.onreadystatechange = function () {
		if (pReqObj.readyState == 4) {
			// hide Loading
			setTransfer(false);
			aInfo = eval(pReqObj.responseText);
			if (aInfo[0]['action'] && aInfo[0]['action'] == 'reauthenticate') { reauthUser('start'); return false; }
			if (xArgs) {
				eval(responseFunction+ "(aInfo[0], xArgs)");
			} else {
				eval(responseFunction+ "(aInfo[0])");
			}
		}
	}
}

// hides everything and reauthenticates the user
function reauthUser(r) {
   	var doc = document.getElementsByTagName("body")[0];
	if (r == 'start') {
		if (getEl('coverall')) { return false; }

	   	// cover everything
  		newEl({"type":"div", "id":"coverall", "style":{"zIndex":10}}, document.body);
	   	// show the login form
   		// FIX FIX FIX place the div in the middle of the screen regardless of the scroll
		var fstyle = {"zIndex":15, "position":"absolute", "top":'100px', "left":'100px'};
		var fattrs = {"width":'0px', "height":'0px', "scrolling":"no", "frameborder":"0px", "src":"reauth.php?username="+ myusername +"&companyid="+ mycompanyid};
   		newEl({"type":"iframe", "id":"reauthform", "style":fstyle, "attributes":fattrs}, document.body);
	} else if (r['auth'] && r['auth'] == 1) {
		// if the auth was successful, unhide everything
	   	doc.removeChild(getEl('coverall'))
	   	doc.removeChild(getEl('reauthform'))
	}
}

// setup/remove the progress bar
function showUploadProgress() {
	var coverall = getEl('coverall');
	var pbContainer = getEl('progressBarContainer');
	var p = arguments[0];

	if (coverall || p == 'stop') {

		if (coverall) {
			coverall.parentNode.removeChild(coverall);
			pbContainer.parentNode.removeChild(pbContainer);
		}

	} else {

		// set the upload id in the form
		var rnd = randomString(10);
		if (p && typeof(p).toLowerCase().lastIndexOf('string') != -1 && getEl(p)) { getEl(p).value = rnd; }
		getEl('APC_UPLOAD_PROGRESS').value = rnd;

		// cover the screen
		coverall = newEl({"type":"div", "id":"coverall", "style":{"zIndex":10}}, document.body);
		coverall.ondblclick = showUploadProgress;

		// create the upload progress bar
		var dstyle = {"zIndex":15, "width":"70%", "top":"30%", "left":"15%"};
		pbContainer = newEl({"type":"div", "class":"iframe", "id":"progressBarContainer", "style":dstyle}, document.body);
		pbContainer.style.visibility = 'visible';
		pbContainer.style.display = '';

		var topC = newEl({"type":"div"}, pbContainer);
		newEl({"type":"span", "class":"lfont thick dark rspace10", "text":"Uploading"}, topC);
		newEl({"type":"span", "class":"sfont", "id":"progressBarMesg", "text":"Getting info please wait."}, topC);
		newEl({"type":"span", "class":"sfont", "id":"progressBarPercent"}, topC);
		newEl({"type":"span", "class":"sfont rspace10", "id":"progressBarSizeTotal"}, topC);
		var bottomC = newEl({"type":"div", "class":"tspace10", "id":"progressBarPercentBar", "style":{"width":"1%", "height":"30px", "backgroundColor":"#9acd32"}}, pbContainer);

		setTimeout('getAjaxInfo({"url":"ajax.php?feat=upload_status&upload_id="+getEl("APC_UPLOAD_PROGRESS").value, "handler":"updateUploadProgress"})', 5000);
	}
}

// updates the progress bar
function updateUploadProgress(e) {
	var coverall = getEl('coverall');
	var pbContainer = getEl('progressBarContainer');

	// if the progress bar is already cleared because the upload finised, then clear
	if (!coverall) { return; }
	if (e['total'] == e['current']) { showUploadProgress('stop'); return; }

	getEl('progressBarMesg').innerHTML = '';
	var percentUp = Math.round(parseInt(e['bytes_uploaded'], 10) / parseInt(e['bytes_total'], 10) * 100);
	setText(getEl('progressBarPercent'), percentUp +'% of ');
	setText(getEl('progressBarSizeTotal'), readableSize(e['bytes_total']));
	getEl('progressBarPercentBar').style.width = percentUp.toString() +'%';

	setTimeout('getAjaxInfo({"url":"ajax.php?feat=upload_status&upload_id="+getEl("APC_UPLOAD_PROGRESS").value, "handler":"updateUploadProgress"})', 3000);
}

// this function shows when an ajax request is happening
function setTransfer(command) {
	theItem = getEl('ajaxLoading', true);
	if (!theItem) { return false; }
	if (command) {
		theItem.style.visibility = 'visible';
	} else {
		theItem.style.visibility = 'hidden';
	}
}

function showAjaxResponse(p) {
	if (p['error']) { alert(p['error']); }
	if (p['message']) { alert(p['message']); }
}

function newEl() {
	params = arguments[0];
	theDoc = (arguments[0]['toparent'] == '1')?parent.document:document;
	newElement = theDoc.createElement(params['type']);
	// hack for IE and hidden inputs
	if(params['attributes'] && params['attributes']['type']) { newElement.setAttribute('type', params['attributes']['type']); }
	// if we have a second argument, its the parent
	if (arguments.length == 2 && arguments[1] != false) { arguments[1].appendChild(newElement); }
	
	if (params['id']) { newElement.setAttribute('id', params['id']); }
	if (params['class']) { newElement.className = params['class']; }
	if (params['text'] && params['text'].length > 0) {
		if (params['nobr']) {
			var noBr = theDoc.createElement('nobr');
			noBr.appendChild(theDoc.createTextNode(params['text']));
			newElement.appendChild(noBr);
		} else {
			newElement.appendChild(theDoc.createTextNode(params['text']));
		}
	}
	if (params['attributes']) {
		for (var attrs in params['attributes']) {
			try {
				newElement.setAttribute(attrs, params['attributes'][attrs]);
			} catch (err) {
				//alert('Cannot set '+ attrs +' to '+ params['attributes'][attrs]);
			}
		}
	}
	if (params['onclick']) { newElement.onclick = eval(params['onclick']); }
	if (params['ondblclick']) { newElement.ondblclick = eval(params['ondblclick']); }
	if (params['onchange']) { newElement.onchange = eval(params['onchange']); }
	if (params['onkeypress']) { newElement.onkeypress = eval(params['onkeypress']); }
	if (params['onhover']) { newElement.onhover = eval(params['onhover']); }
	if (params['onfocus']) { newElement.onfocus = eval(params['onfocus']); }
	if (params['onblur']) { newElement.onblur = eval(params['onblur']); }
	if (params['value']) { newElement.value = params['value']; }
	if (params['style']) { for (var attrs in params['style']) { newElement['style'][attrs] = params['style'][attrs]; }}
	if (params['src']) { newElement.src = params['src']; }

	return newElement;
}

function setText(theObj, theText) {
	theObj.innerHTML = '';
	theObj.appendChild(document.createTextNode(theText));
}

function getText(theObj) {
	if (theObj.childNodes.length == 0) { return false; }
	if (theObj.firstChild.nodeName.toLowerCase() == '#text') { return theObj.firstChild.nodeValue; }
	for (var i=0; i<theObj.childNodes.length; i++) {
		if (theObj.firstChild.nodeName.toLowerCase() != '#text') { continue; }
		return theObj.childNodes[i].nodeValue;
	}
}

function insertAfter(referenceNode, node) {
	if (referenceNode.nextSibling) { referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling); }
	else { referenceNode.parentNode.appendChild(node); }
}

function checkAttr(theElement, theAttr) {
	try { if (theElement.getAttribute(theAttr) == null) { return false; } } catch (err) { return false; }
	return true;
}

function getEl() {
	if (document.getElementById(arguments[0])) { return document.getElementById(arguments[0]); }
	else if (arguments.length > 1 && arguments[1] == true && parent.document.getElementById(arguments[0])) { return parent.document.getElementById(arguments[0]); }
	else { return false; }
}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		try { window.onload = func; } catch (err) { }
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

function addunLoadEvent(func) {
	var oldunload = window.onunload;
	if (typeof window.onunload != 'function') {
		try { window.onunload = func; } catch (err) { }
	} else {
		window.onunload = function() {
			if (oldunload) {
				oldunload();
			}
			func();
		}
	}
}

function clearListTable() {
	if (arguments.length == 0) { return false; }
	
	var amtRows = arguments[0].tBodies[0].rows.length;
	var startRow = (arguments.length > 1)?arguments[1]:1;

	for (i = startRow; i < amtRows; i++) { arguments[0].tBodies[0].deleteRow(startRow); }

	return true;
}

function bringElementHere() {
	var e = arguments[0];
	var theElement = arguments[1];
	var theOffset = {"x":10,"y":10}
	var mousePos = {};
	var elover = false;

	// get element dimensions
	theElement.style.display = '';
	var elWidth = theElement.offsetWidth
	var elHeight = theElement.offsetHeight;

	//
	// we allow a few options on where the menu goes
	//

	// user clicks on a span that has menu under
	var elunder = findTarget(e, 'span', 'menuunder');
	// user clicks on a button that gets a menu under
	if (!elunder) { elunder = findTarget(e, 'div', 'menuunder'); }
	// user clicks on a button that gets a menu under
	if (!elunder) { elunder = findTarget(e, 'input'); }
	// we are passed an element instead of an event that has a menuunder
	if (!elunder && checkAttr(e, 'menuunder')) { elunder = e; }
	// we are passed an element instead of an even that has a menuover
	if (!elunder && checkAttr(e, 'menuover')) { elover = e; }
	var elside = findTarget(e, 'a', 'side');

	// check if we should have elover instead
	if (elunder && checkAttr(elunder, 'menuover')) { elover = elunder; elunder = false; }

	if (elunder) { // menu under span
		theOffset = {"x":0,"y":2};
		mousePos = findPos(elunder);
		mousePos['y'] = mousePos['y'] + elunder.offsetHeight;
	} else if (elside) {
		mousePos = findPos(elside);
		mousePos['x'] = mousePos['x'] + elside.offsetWidth;
		mousePos['y'] = mousePos['y'] - 10;
	} else if (elover) {
		theOffset = {"x":0,"y":-2};
		mousePos = findPos(elover);
		mousePos['y'] = mousePos['y'] - elHeight;
	} else { // menu under mouse
		// get the mouse pointer location in the document
		// so we know where to position the frame
		// catch for broken IE, it needs event
		try { mousePos = getMousePos(e); } catch (err) { mousePos = getMousePos(event); }
	}

	// get window dimensions
	var winWidth, winHeight;
	if( typeof( window.innerWidth ) == 'number' ) {
		//Non-IE
		winWidth = window.innerWidth;
		winHeight = window.innerHeight;
	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//IE 6+ in 'standards compliant mode'
		winWidth = document.documentElement.clientWidth;
		winHeight = document.documentElement.clientHeight;
	}
	// keep the element in the window
	if (elWidth + mousePos['x'] + theOffset['x'] > winWidth + document.body.scrollLeft) {
		mousePos['x'] = winWidth - theOffset['x'] - elWidth - 10;
	} else { mousePos['x'] = mousePos['x'] + theOffset['x']; }

	if (!elover && !elunder && (elHeight + mousePos['y'] + theOffset['y'] > winHeight + document.body.scrollTop)) {
		mousePos['y'] = winHeight - theOffset['y'] - elHeight - 10;
		if (mousePos['y'] < 10) { mousePos['y'] = 10; } // make sure the top does not go off the screen
	} else { mousePos['y'] = mousePos['y'] + theOffset['y']; }

	// set the frame and make it visible
	theElement.style.left = mousePos['x'] + 'px';
	theElement.style.top = mousePos['y'] + 'px';
	theElement.style.visibility = 'visible';
}

function findPos(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 {"x":curleft, "y":curtop};
}

function getLeft(node) {
	var iLeft = 0;
	while(node.tagName.toLowerCase() != 'body') {
		iLeft += node.offsetLeft;
		node = node.offsetParent;
	}

	return parseInt(iLeft, 10);
}

function getTop(node) {
	var iTop = 0;
	while(node.tagName.toLowerCase() != 'body') {
		iTop += node.offsetTop;
		node = node.offsetParent;
	}

	return parseInt(iTop, 10);
}
 
function hideContainer(theContainer) {
	theContainer.style.left = '10px';
	theContainer.style.top = '10px';
	theContainer.style.visibility = 'hidden';
	theContainer.style.display = 'none';
}

function isNumeric(sText) {
	if ($type(sText) == 'number') { return true; }
	if (sText == null || sText.length == 0) { return false; }
	return (sText.match(/^(-?\d*\.?\d*)$/) != null);
}

function checkNumeric(e) {
	var theInput = findTarget(e, 'input');
	if (!isNumeric(theInput.value)) {
		if (checkAttr(theInput, 'defaultvalue')) {
	theInput.value = theInput.getAttribute('defaultvalue');
		} else {
	theInput.value = 0;
		}
		alert('Please enter a numeric value.');
	}
}

function checkDT(e) {
	var calInput = findTarget(e, 'input', 'caltype');
	if (!calInput) { alert('Calendar input not found'); return false; }
	var calType = calInput.getAttribute('caltype');
	var calHid = (checkAttr(calInput, 'calhid'))?getEl(calInput.getAttribute('calhid')):false;
	var uText = trim(calInput.value);

	if (uText.length == 0) {
		if (calHid) { calHid.value = 0; }
		else { calInput.setAttribute('fulldate', '0'); }
		return false;
	}

	var converted = false;
	var dateObj = new Date();
	var today = new Date();
	var thisyear = today.getFullYear();
	var viewdate = '';
	var fulldate = '';
	var tmp;

	var format_strings = ['#MM#/#DD#/#YY#', '#YYYY#-#MM#-#DD#', ' #h#:#mm# #ampm#', ' #hhh#:#mm#:00'];
	try {
		if (JSON.encode(format_strings).length > 0) {
			format_strings = ['%m/%d/%y', '%Y-%m-%d', ' %I:%M %p', ' %H:%M:00'];
		}
	} catch (err) {}

	if (calType == 'date' || calType == 'datetime') {
		var regd1 = /^([0-9]{1,2})[\/-]([0-9]{1,2})[\/-]([0-9]{2})/; // 1/11/04
		var regd2 = /^([0-9]{1,2})[\/-]([0-9]{1,2})/; // 1/11
		var regd3 = /^([0-9]{1,2})[\/-]([0-9]{1,2})[\/-]([0-9]{4})/; // 1/11/2004
		var regd4 = /^([0-9]{4})[\/-]([0-9]{2})[\/-]([0-9]{2})/; // 2004-01-11

		if (regd1.test(uText)) {
			tmp = regd1.exec(uText);
			tmp[3] = (parseInt(tmp[3],10) < 70)?'20'+ tmp[3]:'19'+ tmp[3];
			dateObj.setFullYear(tmp[3], parseInt(tmp[1], 10)-1, tmp[2]);
		} else if (regd2.test(uText)) {
			tmp = regd2.exec(uText);
			dateObj.setFullYear(today.getFullYear(), parseInt(tmp[1], 10)-1, tmp[2]);
		} else if (regd3.test(uText)) {
			tmp = regd3.exec(uText);
			dateObj.setFullYear(tmp[3], parseInt(tmp[1], 10)-1, tmp[2]);
		} else if (regd4.test(uText)) {
			tmp = regd4.exec(uText);
			dateObj.setFullYear(tmp[3], parseInt(tmp[1], 10)-1, tmp[2]);
		} else {
			calInput.value = 'Please try again.'; calShow(calInput); return false;
		}

		viewdate += dateObj.format(format_strings[0]);
		fulldate += dateObj.format(format_strings[1]);
	}

	if (calType == 'time' || calType == 'datetime') {
		var regt1 = /([0-9]{1,2}):([0-9]{2})\s?([a|p]m)$/i; // 3:30pm
		var regt2 = /([0-9]{1,2})\s?([a|p]m)$/i; // 3pm
		var regt3 = /([0-9]{2}):([0-9]{2}):([0-9]{2})$/; // 15:30:00

        if (regt1.test(uText)) {
            tmp = regt1.exec(uText);
            tmp[1] = parseInt(tmp[1], 10);
            if (tmp[3].toLowerCase() == 'pm' && tmp[1] < 12) { tmp[1] += 12; }
            if (tmp[3].toLowerCase() == 'am' && tmp[1] == 12) { tmp[1] = 0; }
            dateObj.setHours(tmp[1], tmp[2], 0);
        } else if (regt2.test(uText)) {
            tmp = regt2.exec(uText);
            tmp[1] = parseInt(tmp[1], 10);
            if (tmp[2].toLowerCase() == 'pm' && tmp[1] < 12) { tmp[1] += 12; }
            if (tmp[2].toLowerCase() == 'am' && tmp[1] == 12) { tmp[1] = 0; }
            dateObj.setHours(tmp[1], 0, 0);
        } else if (regt3.test(uText)) {
            tmp = regt3.exec(uText);
            dateObj.setHours(tmp[1], tmp[2], tmp[3]);
        } else {
            calInput.value = 'Please try again.'; calInput.select(); return false;
        }

		viewdate += dateObj.format(format_strings[2]);
		fulldate += dateObj.format(format_strings[3]);
	}

	if (calHid) { calHid.value = trim(fulldate) } else { calInput.setAttribute('fulldate', trim(fulldate)); }
	calInput.value = trim(viewdate);
	calHide();
	return true;
}

function showUpdateTime(theElement) {
	var right_now = new Date();
	setText(theElement, right_now.format('#h#:#mm#:#ss#'));
}

function randomString(slength) {
	var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var randomstring = '';
	for (var i=0; i<slength; i++) {
		var rnum = Math.floor(Math.random() * chars.length);
		randomstring += chars.charAt(rnum);
	}
	return randomstring;
}

function toggleCb() {
	// find the right element
	var e = arguments[0];
	var theSpan = findTarget(e, 'span', 'hid');
	if (!theSpan) { theSpan = findTarget(e, 'div', 'hid'); }
	if (!theSpan && checkAttr(e, 'hid')) { theSpan = e; }
	if (!theSpan) { return false; }

	var hidInput = getEl(theSpan.getAttribute('hid'));
	var result; // the variable = true if the object will be selected, false otherwise

	// if we have a specific task
	if (arguments.length > 1) {
		result = (arguments[1] == 'check');
	} else { // figure out what we have to do
		if (hidInput) { result = (hidInput.value == '0'); }
		else { result = (theSpan.getAttribute('hid') == '0'); }
	}

	// set the hid
	if (hidInput) { hidInput.value = (result)?1:0; }
	else { theSpan.setAttribute('hid', (result)?1:0); }

	// set the class
	if (result) {
		if (theSpan.className.indexOf('fakecbx') == -1) { theSpan.className = theSpan.className.replace(/fakecb/, 'fakecbx'); }
	} else {
		theSpan.className = theSpan.className.replace(/fakecbx/, 'fakecb');
	}

	return true;
}

function focusSelectAll(e) {
	var element = findTarget(e, 'input');
	if (!element) {
		element = findTarget(e, 'textarea');
		if (!element) { return false; }
	}

	element.select();
}

function chooseCompany(e) {
	if (e['status']) {
		if (e['status'] == 1) {
			window.location.href = window.location.href;
		} else {
			if (e['error']) {
				alert(e['error']);
			} else {
				alert('Error changing companies.');
			}
		}
		return true;
	}

	hidemenu();
	var link = findTarget(e, 'a', 'companyid');
	if (!link) { alert('Company information not found.'); return false; }

	var companyid = link.getAttribute('companyid');
	if (companyid == mycompanyid) { return false; }
	getAjaxInfo({"url":"ajax.php?feat=session&command=switchcompany&companyid="+ companyid,"handler":"chooseCompany"});
}

function getFilename(fullpath) {
	if (fullpath.lastIndexOf('/') == -1) { // if windir
		return fullpath.substring(fullpath.lastIndexOf('\\')+1, fullpath.length);
	} else if (fullpath.lastIndexOf('\\') == -1) { // if unixdir
		return fullpath.substring(fullpath.lastIndexOf('/')+1, fullpath.length);
	} else { // do more checks
		return 'na';
	}
}

function toggleTbody(e) {

	target = false;
	// the try statements are for broken IE
	if (window.event && window.event.srcElement) {
		try { target = window.event.srcElement; }
		catch (err) { alert('window.event '+ err.description); }
	} else {
		try { target = e.target; }
		catch (err) { alert('target error:'+ err.description); }
	}

	// make sure that the element has the attribute
	if (!checkAttr(target, 'tbodyid')) { return false; }

	// get the tbody
	var theTbody = getEl(target.getAttribute('tbodyid'));

	// change the style display
	var currentDisplay = theTbody.style.display;
	if (currentDisplay == 'none') {
		theTbody.style.display = '';
		if (target.nodeName.toLowerCase() == 'img') { target.src = 'images/minus.gif'; }
		return 'opened';
	} else {
		theTbody.style.display = 'none';
		if (target.nodeName.toLowerCase() == 'img') { target.src = 'images/plus.gif'; }
		return 'closed';
	}
}

function setMenu2Obj(obj, contents, scrollbox) {
	if (checkAttr(obj, 'click') && obj.getAttribute('click') == 1) { 
		obj.onclick = function (e) { dropdownmenu(obj, e, contents, scrollbox); }
	} else {
		obj.onclick = function (e) { return clickreturnvalue(); }
		obj.onmouseover = function (e) { dropdownmenu(obj, e, contents, scrollbox); }
	}
	obj.onmouseout = delayhidemenu;
}

function setCaretPosition(ctrl, pos) {
	if(ctrl.setSelectionRange) {
		ctrl.focus();
		ctrl.setSelectionRange(pos,pos);
	} else if (ctrl.createTextRange) {
		var range = ctrl.createTextRange();
		range.collapse(true);
		range.moveEnd('character', pos);
		range.moveStart('character', pos);
		range.select();
	}
}

function txtAreaExtend(e) {
	var txtarea = findTarget(e, 'textarea');
	if (!txtarea) { return false; }

	var rows = parseInt(txtarea.rows, 10);
	if (rows < 1) { return false; }
	txtarea.rows = rows+1;

	return true;
}

function jEsc(txt) {
	if (txt.length == 0 || trim(txt).length == 0) { return txt; }
	return txt.replace(/\n/g, '\\n').replace(/"/g, "\\\"");
}

function getXmlElements(theNode) {
	if (!theNode) { return false; }
	var xmlArray = new Array();
	var theEl = null;
	for (var e=0; e<theNode.childNodes.length; e++) {
		if (theNode.childNodes[e].nodeName.toLowerCase() != '#text') {
			theEl = theNode.childNodes[e];
			xmlArray[theEl.nodeName] = (theEl.childNodes.length > 0)?theEl.firstChild.nodeValue:'';
		}
	}
	return xmlArray;
}

function getXmlAttributes(theNode) {
	var xmlArray = new Array();
	var theAttrs = theNode.attributes;
	for (var a=0; a<theAttrs.length; a++) {
		xmlArray[theAttrs[a].name] = theAttrs[a].value;
	}
	return xmlArray;
}

function qEscapeXML(text) {
	text = text.replace(/&/gm, '&amp;');
	text = text.replace(/</gm, '&lt;');
	text = text.replace(/>/gm, '&gt;');
	text = text.replace(/"/gm, '&quot;');
	text = text.replace(/'/gm, '&apos;');

	return text;
}

/*
Date.prototype.format=function(formatString){
	//if (!isNumeric(formatString)) { return ''; }
	var YYYY,YY,MMMM,MMM,MM,M,DDDD,DDD,DD,D,hhh,hh,h,mm,m,ss,s,ampm,dMod,th;
	YY = ((YYYY=this.getFullYear())+"").substr(2,2);
	MM = (M=this.getMonth()+1)<10?('0'+M):M;
	MMM = (MMMM=["January","February","March","April","May","June","July","August","September","October","November","December"][M-1]).substr(0,3);
	DD = (D=this.getDate())<10?('0'+D):D;
	DDD = (DDDD=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][this.getDay()]).substr(0,3);
	th=(D>=10&&D<=20)?'th':((dMod=D%10)==1)?'st':(dMod==2)?'nd':(dMod==3)?'rd':'th';
	formatString = formatString.replace("#YYYY#",YYYY).replace("#YY#",YY).replace("#MMMM#",MMMM).replace("#MMM#",MMM).replace("#MM#",MM).replace("#M#",M).replace("#DDDD#",DDDD).replace("#DDD#",DDD).replace("#DD#",DD).replace("#D#",D).replace("#th#",th);
	 h=(hhh=this.getHours());
	if (h==0) h=24;
	if (h>12) h-=12;
	hh = h<10?('0'+h):h;
	ap=(AP=(AMPM=(ampm=hhh<12?'am':'pm').toUpperCase()).substr(0,1)).toLowerCase();
	mm=(m=this.getMinutes())<10?('0'+m):m;
	ss=(s=this.getSeconds())<10?('0'+s):s;
	return formatString.replace("#hhh#",hhh).replace("#hh#",hh).replace("#h#",h).replace("#mm#",mm).replace("#m#",m).replace("#ss#",ss).replace("#s#",s).replace("#ampm#",ampm).replace("#AMPM#",AMPM).replace("#AP#",AP).replace("#ap#",ap);
}
*/
 
function addCommas(nStr) {
	nStr += '';
	var x = nStr.split('.');
	var x1 = x[0];
	var x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); }
	return x1 + x2;
}

function stripslashes(str) {
	try { return str.replace(/\\'/g,'\'').replace(/\\"/g,'"').replace(/\\\\/g,'\\').replace(/\\0/g,'\0'); } catch (err) { return str; }
}

// this is a common function which will help sort an associative array based on a field
// it expect 2 global parameters to be set, 1. js_sort_field & 2. js_sort_direction
function jsSortArrString(a, b) {
	var x = y = '';

    try { x = trim(a[app_global['js_sort_field']]).toLowerCase(); } catch (err) {}
    try { y = trim(b[app_global['js_sort_field']]).toLowerCase(); } catch (err) {}
    if (app_global['js_sort_direction'] == 'desc') { return ((x > y) ? -1 : ((x < y) ? 1 : 0)); }
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}   
    
function jsSortArrFloat(a, b) {
    var x = parseFloat(a[app_global['js_sort_field']]);
    var y = parseFloat(b[app_global['js_sort_field']]);
    if (app_global['js_sort_direction'] == 'desc') { return ((x > y) ? -1 : ((x < y) ? 1 : 0)); }
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

// cookie related functions
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*86400000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}
//*****************************************************************************
// Do not remove this notice.
//
// Copyright 2001 by Mike Hall.
// See http://www.brainjar.com for terms of use.
//*****************************************************************************

// Determine browser and version.

function Browser() {

	var ua, s, i;

	this.isIE		= false;
	this.isNS		= false;
	this.version = null;

	ua = navigator.userAgent;

	s = "MSIE";
	if ((i = ua.indexOf(s)) >= 0) {
		this.isIE = true;
		this.version = parseFloat(ua.substr(i + s.length));
		return;
	}

	s = "Netscape6/";
	if ((i = ua.indexOf(s)) >= 0) {
		this.isNS = true;
		this.version = parseFloat(ua.substr(i + s.length));
		return;
	}

	// Treat any other "Gecko" browser as NS 6.1.

	s = "Gecko";
	if ((i = ua.indexOf(s)) >= 0) {
		this.isNS = true;
		this.version = 6.1;
		return;
	}
}

var browser = new Browser();

// Global object to hold drag information.

var dragObj = new Object();
dragObj.zIndex = 0;

function dragStart(event, id) {

	var el;
	var x, y;

	// If an element id was given, find it. Otherwise use the element being
	// clicked on.

	if (id)
		dragObj.elNode = document.getElementById(id);
	else {
		if (browser.isIE)
			dragObj.elNode = window.event.srcElement;
		if (browser.isNS)
			dragObj.elNode = event.target;

		// If this is a text node, use its parent element.

		if (dragObj.elNode.nodeType == 3)
			dragObj.elNode = dragObj.elNode.parentNode;
	}

	// Get cursor position with respect to the page.

	if (browser.isIE) {
		x = window.event.clientX + document.documentElement.scrollLeft
			+ document.body.scrollLeft;
		y = window.event.clientY + document.documentElement.scrollTop
			+ document.body.scrollTop;
	}
	if (browser.isNS) {
		x = event.clientX + window.scrollX;
		y = event.clientY + window.scrollY;
	}

	// Save starting positions of cursor and element.

	dragObj.cursorStartX = x;
	dragObj.cursorStartY = y;
	dragObj.elStartLeft	= parseInt(dragObj.elNode.style.left, 10);
	dragObj.elStartTop	 = parseInt(dragObj.elNode.style.top,	10);

	if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
	if (isNaN(dragObj.elStartTop))	dragObj.elStartTop	= 0;

	// Update element's z-index.

	//dragObj.elNode.style.zIndex = ++dragObj.zIndex;

	// Capture mousemove and mouseup events on the page.

	if (browser.isIE) {
		document.attachEvent("onmousemove", dragGo);
		document.attachEvent("onmouseup",	 dragStop);
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
	if (browser.isNS) {
		document.addEventListener("mousemove", dragGo,	 true);
		document.addEventListener("mouseup",	 dragStop, true);
		event.preventDefault();
	}
}

function dragGo(event) {

	var x, y;

	// Get cursor position with respect to the page.

	if (browser.isIE) {
		x = window.event.clientX + document.documentElement.scrollLeft
			+ document.body.scrollLeft;
		y = window.event.clientY + document.documentElement.scrollTop
			+ document.body.scrollTop;
	}
	if (browser.isNS) {
		x = event.clientX + window.scrollX;
		y = event.clientY + window.scrollY;
	}

	// Move drag element by the same amount the cursor has moved.

	dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
	dragObj.elNode.style.top	= (dragObj.elStartTop	+ y - dragObj.cursorStartY) + "px";

	if (browser.isIE) {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
	if (browser.isNS) { event.preventDefault(); }
}

function dragStop(event) {

	// Stop capturing mousemove and mouseup events.

	if (browser.isIE) {
		document.detachEvent("onmousemove", dragGo);
		document.detachEvent("onmouseup",	 dragStop);
	}
	if (browser.isNS) {
		document.removeEventListener("mousemove", dragGo,	 true);
		document.removeEventListener("mouseup",	 dragStop, true);
	}
}
function getposOffset(what, offsettype){
var totaloffset=(offsettype=="left")? what.offsetLeft : what.offsetTop;
var parentEl=what.offsetParent;
while (parentEl!=null) {
totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
parentEl=parentEl.offsetParent;
}
if (dropmenuobj.scroll) { totaloffset=(offsettype=="left")? totaloffset-dropmenuobj.scroll.scrollLeft : totaloffset-dropmenuobj.scroll.scrollTop; }
return totaloffset;
}

function showhide(obj, e, visible, hidden){
if (ie4||ns6)
dropmenuobj.style.left=dropmenuobj.style.top="-500px"
if (menuwidth!=""){
//dropmenuobj.widthobj=dropmenuobj.style
//dropmenuobj.widthobj.width=menuwidth
}
//if (ie4) { dropmenuobj.style.width='20px'; }
if (!e) { e = window.event; } // for broken IE with setMenu2Obj
if (e.type=="click" && obj.visibility==hidden || e.type=="mouseover") { obj.visibility=visible }
else if (e.type=="click") { obj.visibility=hidden }
}

function iecompattest(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

function clearbrowseredge(obj, whichedge){
var edgeoffset=0
if (whichedge=="rightedge"){
var windowedge=ie4 && !window.opera? iecompattest().scrollLeft+iecompattest().clientWidth-15 : window.pageXOffset+window.innerWidth-15
dropmenuobj.contentmeasure=dropmenuobj.offsetWidth
if (windowedge-dropmenuobj.x < dropmenuobj.contentmeasure)
edgeoffset=dropmenuobj.contentmeasure-obj.offsetWidth
}
else{
var topedge=ie4 && !window.opera? iecompattest().scrollTop : window.pageYOffset
var windowedge=ie4 && !window.opera? iecompattest().scrollTop+iecompattest().clientHeight-15 : window.pageYOffset+window.innerHeight-18
dropmenuobj.contentmeasure=dropmenuobj.offsetHeight
if (windowedge-dropmenuobj.y < dropmenuobj.contentmeasure){ //move up?
edgeoffset=dropmenuobj.contentmeasure+obj.offsetHeight
if ((dropmenuobj.y-topedge)<dropmenuobj.contentmeasure) //up no good either?
edgeoffset=dropmenuobj.y+obj.offsetHeight-topedge
}
}
return edgeoffset
}

function populatemenu(what){
if (ie4||ns6)
dropmenuobj.innerHTML='<table class="sfont"><tr><td>'+ what.join("") +'</td></tr></table>';
}


function dropdownmenu(obj, e, menucontents, scrollbox){
if (menucontents.length == 0) { return false; }
if (window.event) event.cancelBubble=true
else if (e.stopPropagation) e.stopPropagation()
clearhidemenu()
dropmenuobj=document.getElementById? document.getElementById("dropmenudiv") : dropmenudiv
populatemenu(menucontents)
try { var ddmenulink = (e.target)?e.target:false; } catch (err) { }
if (!ddmenulink) { ddmenulink = findTarget(e, 'span'); }
if (!ddmenulink) { ddmenulink = findTarget(e, 'a'); }
if (!ddmenulink) { ddmenulink = findTarget(e, 'input'); }
if (!ddmenulink) { ddmenulink = false; }
dropmenuobj.ddlink = ddmenulink;
dropmenuobj.scroll = (scrollbox)?scrollbox:false;

if (ie4||ns6){
showhide(dropmenuobj.style, e, "visible", "hidden", menuwidth)
dropmenuobj.x=getposOffset(obj, "left")
dropmenuobj.y=getposOffset(obj, "top")
dropmenuobj.style.left=dropmenuobj.x-clearbrowseredge(obj, "rightedge")+"px"
dropmenuobj.style.top=dropmenuobj.y-clearbrowseredge(obj, "bottomedge")+obj.offsetHeight+"px"
}

return clickreturnvalue()
}

function clickreturnvalue(){
if (ie4||ns6) return false
else return true
}

function contains_ns6(a, b) {
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}

function dynamichide(e){
if (ie4&&!dropmenuobj.contains(e.toElement))
delayhidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
delayhidemenu()
}

function hidemenu(e){
if (typeof dropmenuobj!="undefined"){
if (ie4||ns6)
dropmenuobj.style.visibility="hidden"
dropmenuobj.style.top="20px";
dropmenuobj.style.left="20px";
}
}

function delayhidemenu(){
if (ie4||ns6)
delayhide=setTimeout("hidemenu()",disappeardelay)
}

function clearhidemenu(){
if (typeof delayhide!="undefined")
clearTimeout(delayhide)
}

function checkFileExt() { 
    var filename = arguments[0];
    var exts = (arguments.length > 1)?arguments[1]:valid_exts;

    var fileext = filename.substring(filename.lastIndexOf('.'), filename.length);
    if (!inArray(fileext.toLowerCase(), exts)) {
        alert('File '+ filename +'\n'+ fileext +' is not a valid extensions.\n\nValid Extensions: '+ exts.join(' ') +'.');
        return false;
    }
    return true;
}

function checkFilename(p) {
    if (!checkFileExt(p['file'], p['exts'])) { return false; }
    if (p['file'].indexOf(p['basename']) == -1) { alert('The document you are trying to upload is not named after job#-item#, please rename it.'); return false; }
    return true;
}

/**
 * http://www.openjs.com/scripts/events/keyboard_shortcuts/
 * Version : 2.01.A
 * By Binny V A
 * License : BSD
 */
shortcut = {
	'all_shortcuts':{},//All the shortcuts are stored in this array
	'add': function(shortcut_combination,callback,opt) {
		//Provide a set of default options
		var default_options = {
			'type':'keydown',
			'propagate':false,
			'disable_in_input':false,
			'target':document,
			'keycode':false
		}
		if(!opt) opt = default_options;
		else {
			for(var dfo in default_options) {
				if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
			}
		}

		var ele = opt.target
		if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
		var ths = this;
		shortcut_combination = shortcut_combination.toLowerCase();

		//The function to be called at keypress
		var func = function(e) {
			e = e || window.event;
			
			if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
				var element;
				if(e.target) element=e.target;
				else if(e.srcElement) element=e.srcElement;
				if(element.nodeType==3) element=element.parentNode;

				if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
			}
	
			//Find Which key is pressed
			if (e.keyCode) code = e.keyCode;
			else if (e.which) code = e.which;
			var character = String.fromCharCode(code).toLowerCase();
			
			if(code == 188) character=","; //If the user presses , when the type is onkeydown
			if(code == 190) character="."; //If the user presses , when the type is onkeydown
	
			var keys = shortcut_combination.split("+");
			//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
			var kp = 0;
			
			//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
			var shift_nums = {
				"`":"~",
				"1":"!",
				"2":"@",
				"3":"#",
				"4":"$",
				"5":"%",
				"6":"^",
				"7":"&",
				"8":"*",
				"9":"(",
				"0":")",
				"-":"_",
				"=":"+",
				";":":",
				"'":"\"",
				",":"<",
				".":">",
				"/":"?",
				"\\":"|"
			}
			//Special Keys - and their codes
			var special_keys = {
				'esc':27,
				'escape':27,
				'tab':9,
				'space':32,
				'return':13,
				'enter':13,
				'backspace':8,
	
				'scrolllock':145,
				'scroll_lock':145,
				'scroll':145,
				'capslock':20,
				'caps_lock':20,
				'caps':20,
				'numlock':144,
				'num_lock':144,
				'num':144,
				
				'pause':19,
				'break':19,
				
				'insert':45,
				'home':36,
				'delete':46,
				'end':35,
				
				'pageup':33,
				'page_up':33,
				'pu':33,
	
				'pagedown':34,
				'page_down':34,
				'pd':34,
	
				'left':37,
				'up':38,
				'right':39,
				'down':40,
	
				'f1':112,
				'f2':113,
				'f3':114,
				'f4':115,
				'f5':116,
				'f6':117,
				'f7':118,
				'f8':119,
				'f9':120,
				'f10':121,
				'f11':122,
				'f12':123
			}
	
			var modifiers = { 
				shift: { wanted:false, pressed:false},
				ctrl : { wanted:false, pressed:false},
				alt  : { wanted:false, pressed:false},
				meta : { wanted:false, pressed:false}	//Meta is Mac specific
			};
                        
			if(e.ctrlKey)	modifiers.ctrl.pressed = true;
			if(e.shiftKey)	modifiers.shift.pressed = true;
			if(e.altKey)	modifiers.alt.pressed = true;
			if(e.metaKey)   modifiers.meta.pressed = true;
                        
			for(var i=0; k=keys[i],i<keys.length; i++) {
				//Modifiers
				if(k == 'ctrl' || k == 'control') {
					kp++;
					modifiers.ctrl.wanted = true;

				} else if(k == 'shift') {
					kp++;
					modifiers.shift.wanted = true;

				} else if(k == 'alt') {
					kp++;
					modifiers.alt.wanted = true;
				} else if(k == 'meta') {
					kp++;
					modifiers.meta.wanted = true;
				} else if(k.length > 1) { //If it is a special key
					if(special_keys[k] == code) kp++;
					
				} else if(opt['keycode']) {
					if(opt['keycode'] == code) kp++;

				} else { //The special keys did not match
					if(character == k) kp++;
					else {
						if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
							character = shift_nums[character]; 
							if(character == k) kp++;
						}
					}
				}
			}

			if(kp == keys.length && 
						modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
						modifiers.shift.pressed == modifiers.shift.wanted &&
						modifiers.alt.pressed == modifiers.alt.wanted &&
						modifiers.meta.pressed == modifiers.meta.wanted) {
				callback(e);
	
				if(!opt['propagate']) { //Stop the event
					//e.cancelBubble is supported by IE - this will kill the bubbling process.
					e.cancelBubble = true;
					e.returnValue = false;
	
					//e.stopPropagation works in Firefox.
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
					return false;
				}
			}
		}
		this.all_shortcuts[shortcut_combination] = {
			'callback':func, 
			'target':ele, 
			'event': opt['type']
		};
		//Attach the function with the event
		if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
		else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
		else ele['on'+opt['type']] = func;
	},

	//Remove the shortcut - just specify the shortcut and I will remove the binding
	'remove':function(shortcut_combination) {
		shortcut_combination = shortcut_combination.toLowerCase();
		var binding = this.all_shortcuts[shortcut_combination];
		delete(this.all_shortcuts[shortcut_combination])
		if(!binding) return;
		var type = binding['event'];
		var ele = binding['target'];
		var callback = binding['callback'];

		if(ele.detachEvent) ele.detachEvent('on'+type, callback);
		else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
		else ele['on'+type] = false;
	}
}

function getString(str) {
    try { if (app_global['strings'][str]) { return app_global['strings'][str]; } } catch (err) { }
    return '*'+ str;
}

function handleResponse(r) {
	if (r['status'] == 0) {
		alert(r['error']);
		return false;
	}

	return true;
}

function downloadFile(e) {
	var target = findTarget(e, 'div', 'filename');
	if (!target) { target = findTarget(e, 'span', 'filename'); }
    downloadLocation = 'download.php?folder='+ target.getAttribute('folder') +'&file='+ target.getAttribute('filename');
    window.hidframe.location.href = downloadLocation;
}

function rmapos(e) {
    var obj = findTarget(e, 'input');
    if (obj == false || obj == null) { obj = findTarget(e, 'textarea'); }
    if (obj == false || obj == null) { return false; }

    var str = obj.value;
    str = str.replace(/'/g, "`");
    str = str.replace(/"/g, "``");
    str = str.replace(/\\/g, "/");
    obj.value = str;         
}

function addComment(info) {
	var tmp = null, inp = null;

	// create the form
	var comment_box = $('add_comment_container');

	if (!comment_box) {
		comment_box = newEl({"type":"div", "class":"iframe", "attributes":{"id":"add_comment_container"}}, document.body); 
		newEl({"type":"div", "class":"light xxlfont bspace10", "text":"Add Comment"}, comment_box); 
		newEl({"type":"span", "class":"xlink", "text":"\u03A7", "attributes":{"id":"ac_hide"}}, comment_box);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, comment_box);
		newEl({"type":"div", "class":"standardlable", "text":"Job ID:"}, tmp);
		newEl({"type":"input", "attributes":{"id":"ac_jobid", "type":"text", "value":"", "size":"10"}}, tmp);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, comment_box);
		newEl({"type":"div", "class":"standardlable", "text":"Item ID:"}, tmp);
		newEl({"type":"input", "attributes":{"id":"ac_itemid", "type":"text", "value":"", "size":"3"}}, tmp);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, comment_box);
		newEl({"type":"div", "class":"standardlable", "text":"Comment:"}, tmp);
		inp = newEl({"type":"input", "attributes":{"id":"ac_comment", "type":"text", "value":"", "size":"40"}}, tmp);
		inp.addEvent('keydown', function (e) {
			if (e.key == 'enter') { submitComment(); }
			if (e.key == 'esc') { hideCover($('add_comment_container')); }
		});
		newEl({"type":"input", "attributes":{"id":"ac_feature", "type":"hidden", "value":""}}, tmp);

		tmp = newEl({"type":"div", "class":"sfont alignc cb"}, comment_box);
		newEl({"type":"input", "class":"tspace20", "attributes":{"id":"ac_save", "type":"button", "value":"Save Comment"}}, tmp);
	}

	// setup events
	$('ac_hide').onclick = function (e) { hideCover($('add_comment_container')); }
	$('ac_save').onclick = function (e) { submitComment(); }

	// populate the form
	if (info['jobid'] != null) { $('ac_jobid').value = info['jobid']; }
	if (info['itemid'] != null) { $('ac_itemid').value = info['itemid']; }
	if (info['comment'] != null) { $('ac_comment').value = info['comment']; }
	if (info['feature'] != null && info['feature'].length > 0) { $('ac_feature').value = info['feature']; }

	// put it in the correct location
	var winsize = document.body.getSize();
	//alert(JSON.encode(winsize));
	comment_box.style.width = '500px';
	comment_box.style.left = '50%';
	comment_box.style.marginLeft = '-250px';
	comment_box.style.zIndex = 15;
	var scroll = document.body.getScroll();
	comment_box.style.top = (scroll['y'] +50) +'px';
	//comment_box.setPosition({'y':(scroll['y'] +50)});

	// show the form
	showCover(comment_box);

	$('ac_comment').select();
}

function submitComment() {
	if (!$('ac_jobid')) { return false; }

	var info = {};
	info['jobid'] = trim($('ac_jobid').value);
	info['itemid'] = trim($('ac_itemid').value);
	info['comment'] = trim($('ac_comment').value);

	// basic checks
	if (info['jobid'].length == 0) { alert('Please specifiy a Job ID'); return false; }
	if (info['itemid'].length == 0) { alert('Please specifiy a Item ID'); return false; }
	if (info['comment'].length == 0) { alert('Please specifiy a comment'); return false; }

	var feature = trim($('ac_feature').value);
	if (feature != null && feature.length > 0) { info['feature'] = feature; }

	var postData = {"feat":"Inventory", "command":"add_comment", "info":info};
    new Request({"method":"post", "url":"ajax.php", "data":postData, "onComplete": function (r) {
	    if (!handleResponse(JSON.decode(r))) { return false; }

		// hide the comments
		hideCover($('add_comment_container'));
	}}).send(); 		 
}

function uploadDocument(info) {
	var tmp = null, inp = null;

	// create the form
	var docupload_box = $('upload_document_box');

	if (!docupload_box) {
		docupload_box = newEl({"type":"div", "class":"iframe", "attributes":{"id":"upload_document_box"}}, document.body); 

		var frm = newEl({"type":"form", "id":"upload_document_form", "attributes":{"method":"post", "enctype":"multipart/form-data", "action":"ajax.php?feat=Inventory&command=update_document", "target":"hidframe"}}, docupload_box);

		newEl({"type":"div", "class":"light xxlfont bspace20", "text":"Upload Document"}, frm); 
		newEl({"type":"span", "class":"xlink", "text":"\u03A7", "attributes":{"id":"ud_hide"}}, frm);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, frm);
		newEl({"type":"div", "class":"standardlable", "text":"Job ID:"}, tmp);
		newEl({"type":"input", "attributes":{"id":"ud_jobid", "name":"info[jobid]", "type":"text", "value":"", "size":"10"}}, tmp);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, frm);
		newEl({"type":"div", "class":"standardlable", "text":"Item ID:"}, tmp);
		newEl({"type":"input", "attributes":{"id":"ud_itemid", "name":"info[itemid]", "type":"text", "value":"", "size":"3"}}, tmp);

		tmp = newEl({"type":"div", "class":"sfont inputcontainer"}, frm);
		newEl({"type":"div", "class":"standardlable", "text":"Document:"}, tmp);
		inp = newEl({"type":"div"}, tmp);
		//inp = newEl({"type":"input", "attributes":{"type":"file", "id":"ud_document", "name":"document", "size":"40"}}, tmp);';

		// add callback if defined
		if (info['callback']) { newEl({"type":"input", "attributes":{"name":"callback", "type":"hidden", "value":info['callback']}}, frm); }

		tmp = newEl({"type":"div", "class":"sfont alignc cb"}, frm);
		newEl({"type":"input", "class":"tspace20", "attributes":{"id":"ud_save", "type":"button", "value":"Upload Document"}}, tmp);
	}

	docupload_box.firstChild.childNodes[4].childNodes[1].innerHTML = '<input type="file" name="document" id="ud_document" size="40"/>';

	// setup events
	$('ud_hide').onclick = function (e) { hideCover($('upload_document_box')); }
	$('ud_save').onclick = function (e) { submitDocument(); }

	// populate the form
	if (info['jobid'] != null) { $('ud_jobid').value = info['jobid']; }
	if (info['itemid'] != null) { $('ud_itemid').value = info['itemid']; }

	// put it in the correct location
	var winsize = document.body.getSize();
	//alert(JSON.encode(winsize));
	docupload_box.style.width = '500px';
	docupload_box.style.left = '50%';
	docupload_box.style.marginLeft = '-250px';
	docupload_box.style.zIndex = 15;
	var scroll = document.body.getScroll();
	docupload_box.style.top = (scroll['y'] +50) +'px';

	// show the form
	showCover(docupload_box);
}

function submitDocument() {
	// basic checks
	var fullpath = $('ud_document').value.toLowerCase();
	var job_item_re = new RegExp('^'+ $('ud_jobid').value +'-'+ $('ud_itemid').value +'\.');
	var filename = getFilename(fullpath);
	// make sure it is a document
	if (!checkFileExt(fullpath, ['.doc'])) { return false; }
	// make sure it is for this job-item
	if (!filename.match(job_item_re)) { alert('Filename does not match Job-Item. Are you kidding me?'); return false; }

	// submit the form
	$('upload_document_form').submit();

	// clear this thing
	hideCover($('upload_document_box'));
}

function showCover(box) {
    // cover the page
    var cover = newEl({"type":"div", "attributes":{"id":"coverall"}}, document.body);
    var height = getScrollHeight();
    var width = getScrollWidth();
    cover.style.height = height +'px';
    cover.style.width = width +'px';
    cover.ondblclick = function (e) { document.body.removeChild(getEl('coverall')); };

    // set the onresize
    window.oldresize = window.onresize;
    window.onresize = function (e) {
        var height = getScrollHeight();
        var width = getScrollWidth();
        var cover = getEl('coverall');
        cover.style.height = height +'px';
        cover.style.width = width +'px';
    }

    // show the box
    box.style.visibility = 'visible';
    box.style.display = '';
}

function hideCover(box) {
    box.style.display = 'none';
    document.body.removeChild(getEl('coverall'));
}



