/*
	Form and Dom funcitons, do not put any other functions here
	<script>
*/

/*********************************************************************
'***    Program: getElementsByTagWithClass( node, tagName, className )
'***    Type: Function
'***
'***    Function: returns an array of nodes found on specified node based on Tag Name and Class
'***
'***    Parameters: 
			node - node where to look for elements
			tagName - name of tag to find
			className - class name to filter by
'***        
'***    Returns: array of elements
'***    Remarks: none
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 4/28/08
'*********************************************************************/
function getElementsByTagNameWithClass( node, tagName, className ) {

	var elements = node.getElementsByTagName(tagName);
	var arrNodes = new Array(0);
	
	for (var k=0; k<elements.length; k++){
	
		if (elements[k].className == className) {
			// found, increase count
			arrNodes.push(elements[k]);
		}
	}
	return arrNodes;
}

/*********************************************************************
'***    Program: addLoadEvent( func )
'***    Type: Function
'***
'***    Function: safely adds a new load event
'***
'***    Parameters: 
			func - refernce to function which to call onload
'***        
'***    Returns: void
'***    Remarks: none
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 4/28/08
'*********************************************************************/
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} 
	else {
		window.onload = function() {
		  oldonload();
		  func();
		}
	}
}


/*********************************************************************
'***    Program: prepareAllInputsForHints()
'***    Type: Function
'***
'***    Function: prepares all inputs to show hints
'***
'***    Parameters: none
'***        
'***    Returns: void
'***    Remarks: none
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 4/28/08
'*********************************************************************/
function prepareAllInputsForHints() {
	// get all input objects, add onfocus/onblur
	prepareInputsForHints( "input" );
	prepareInputsForHints( "select" );
	prepareInputsForHints( "textarea" );
}


/*********************************************************************
'***    Program: prepareInputsForHints()
'***    Type: Function
'***
'***    Function: prepares all inputs to show hints
'***
'***    Parameters: none
'***        
'***    Returns: void
'***    Remarks: none
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 4/28/08
'*********************************************************************/
function prepareInputsForHints( tag ) {
	// get all input objects, add onfocus/onblur
	
	var inputs = document.getElementsByTagName(tag);
	for (var i=0; i<inputs.length; i++){
		// test to see if the hint span exists first
		if (inputs[i].parentNode.getElementsByTagName("span")[0]) {

			// the span exists!  on focus, show the hint
			addListener(inputs[i], "focus", showHint);

			// when the cursor moves away from the field, hide the hint
			addListener(inputs[i], "blur", hideHint);
		}
		else {
			addListener(inputs[i], "blur", setValid);
		}
		
		// if object has hint atribure, attach additional events
		if (inputs[i].className == "valueHint") {
			addListener(inputs[i], "focus", hideValueHint);
			addListener(inputs[i], "blur", showValueHint);

			// initialize object while working on it
			showValueHintForObject(inputs[i]);
		}
		
	}
}



/*********************************************************************
'***    Program: hideHint( object )
'***    Type: Function
'***
'***    Function: hides hint showing on input/select/text area
'***
'***    Parameters: 
			e - event FF only
'***        
'***    Returns: void
'***	Remarks: designed to be used only onblur event of input with hint
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/21/08
'*********************************************************************/
function hideHint( e ) {
	var obj = getEventSource( e );
	var parentNd = obj.parentNode;
	
	var hint = getElementsByTagNameWithClass(parentNd, "span", "hint")[0];
	if (hint == null) 
		return;
		
	hint.style.display = "none";
	setValid();
}


/*********************************************************************
'***    Function: shows hint showing on input/select/text area
'***
'***    Parameters: 
			e - event FF only
'***        
'***    Returns: void
'***	Remarks: designed to be used only onfocus event of input with hint
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/21/08
'*********************************************************************/
function showHint( e ) {
	var obj = getEventSource( e );
	var parentNd = obj.parentNode;
	var hint = getElementsByTagNameWithClass(parentNd, "span", "hint")[0];

	var input = this;
	hint.style.display = "inline";
    
    var ie = 0;
    var styleLeft = "";
    
    // find fieldset's left
    if (window.navigator.userAgent.indexOf("MSIE 8") >= 0) {
		styleLeft = (ie + obj.offsetLeft + obj.offsetWidth + 15) + "px";
    }
    else if (window.navigator.userAgent.indexOf("MSIE") >= 0) {
    	var ieHint = getElementsByTagNameWithClass(parentNd, "span", "ieHint")[0];

		if (ieHint != null)
		    ie = ieHint.offsetLeft + 15;
		else
			ie = input.offsetLeft + input.offsetWidth + 15;
		styleLeft = ie + "px";
	}
	else {
		styleLeft = (ie + input.offsetLeft + input.offsetWidth + 15) + "px";
	}
	
    hint.style.left =  styleLeft;
}

/*********************************************************************
'***    Function: sets object to valid class
'***
'***    Parameters: none
'***    Returns: void
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/3/08
'*********************************************************************/
function setValid( e ) {
	var obj = getEventSource( e );

	if (obj.className == "invalidField") {
		window.setTimeout( "setValidById( '" + obj.id + "')", 5000 );
	}
}
/*********************************************************************
'***    Function: sets object to valid class by id
'***    Returns: void
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/4/08
'*********************************************************************/
function setValidById( id ) {
	var obj = document.getElementById( id );
	if (obj != null ) {
		 obj.className = "validField";
	}
}

/*********************************************************************
'***    Function: displays a validation alert (div) on the form and sets focus
'***		to the field
'***
'***    Parameters: 
			objectId - id of object to highligh
			validationText - validation text to show
			errorDivId - id of error div to use when showing the messaage. default="errorMessage".
				this can be used to introduce a separate validation message per fieldset or section
'***        
'***    Returns: always returns false to simplify coding when validating forms
'***    Remarks: 
			Assumes and requires a div or other element with ID="errorMessage"
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/2/08
'*********************************************************************/
function validationAlert( objectId, validationText, errorDivId ) {
	// get objects
	if (errorDivId == null)
		errorDivId = "validationMessage";
	var input = document.getElementById(objectId);
	var errorElem = document.getElementById(errorDivId);

	// restyle
	if (errorElem != null) {
		errorElem.innerHTML = validationText;
		errorElem.className = "validationMessage";
		errorElem.style.visibility = "visible";
		errorElem.style.display = "block";
		errorElem.scrollIntoView(false);
	}

	if (input != null) {
		input.className = "invalidField";
		input.focus();
	}
	return false;
}

/*********************************************************************
'***    Function: shows promopt text in an object (input) which is stored in attribute hint
'***		but only if value is empty
'***
'***    Parameters: 
'***		e - event FF only
'***                
'***    Returns: void
'***
'***    Created by: dimab
'***    Changed by: 
'***    Last change: 12/21/2008
'*********************************************************************/
function showValueHint( e ) {
	var obj = getEventSource( e );
	showValueHintForObject(obj);
}
function showValueHintForObject( obj ) {
	// show text
    var promptText = obj.getAttribute("alt");
    
    //alt may not be defined, set to empty string
    promptText = (promptText != null) ? promptText : "";
    
	if (obj.value == "")
		obj.value = promptText;	

}
/*********************************************************************
'***    Function: hides promopt text in an object (input) normally onblur
'***		but only if value is empty
'***
'***    Parameters: 
'***		e - event FF only
'***                
'***    Returns: void
'***
'***    Created by: dimab
'***    Changed by: 
'***    Last change: 12/21/2008
'*********************************************************************/
function hideValueHint( e ) {
	var obj = getEventSource( e );

	// hide text
	var promptText = obj.getAttribute("alt");
	if (obj.value == promptText)
		obj.value = "";
}

/*********************************************************************
'***    Function: adds even to a specified element
'***
'***    Parameters: 
'***		element - ref to any element
			type    - standard event name without "on" for IE
			expression - ref to fn
			bubbling - true to bubble events
'***                
'***    Returns: true if success
'***	Remarks:
			you MUST use getEventSource() function to get reference to object that raised event
			example: addListener(document.body, "load", activateUserName);
			this adds listener to onLoad even of document and will call function activateUserName
'***
'***    Created by: internet source
'***    Changed by: dimab
'***    Last change: 12/21/2008
'*********************************************************************/
function addListener(element, type, expression, bubbling){	
	if (bubbling == null) 
		bubbling = false;

	if(element.addEventListener)	{ // Standard		
		element.addEventListener(type, expression, bubbling);
		return true;
	} else if(element.attachEvent) { // IE
		element.attachEvent('on' + type, expression);
		return true;
	} else return false;
}



/*********************************************************************
'***    Function: returns reference to an object which caused current event
'***
'***    Parameters: 
'***		e - event (FF only) for other browsers this is null.
'***                
'***    Returns: object
'***	Remarks:
			1. designed to be used only within events
			2. if you hook events using addListener, use this function to get reference to the 
			object that caused current event.
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 12/21/2008
'*********************************************************************/
function getEventSource( e ) {

	if (e) if (e.target) return e.target; // FF

	var source = null;
	
	if (this == window)
		source = window.event.srcElement; // IE
	else
		source = this; // Others
	
	return source;
}

/*********************************************************************
'***    Function: calculates offsetX when it's not available (FF does not support it)
'***
'***    Parameters: 
			e - event used to calculate offsetX
'***        
'***    Returns: integer. offset x of event target
'***    Remarks: none
'***
'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 5/26/09
'*********************************************************************/
function getOffsetX(obj, e) {
	if (!obj.offsetParent)
		return 0;
	
	var parent = obj.offsetParent;
	var intOffsetX = obj.offsetLeft;

	while (parent) {
		intOffsetX += parent.offsetLeft;
		parent = parent.offsetParent;
    }
    if (e == null || e.pageX == null ) return intOffsetX;
	    
	return e.pageX - intOffsetX;
}
/* walks objects in offset stack, calculates offsetLeft */
function getOffsetLeft(obj) {
		
	if (!obj.offsetParent)
		return 0;
		
	var parent = obj.offsetParent;
	var intOffsetX = obj.offsetLeft;

	while (parent) {
		intOffsetX += parent.offsetLeft;
		parent = parent.offsetParent;
	}
	return intOffsetX;
}
/* walks objects in offset stack, calculates offsetTop */
function getOffsetTop(obj) {
		
	if (!obj.offsetParent)
		return 0;
		
	var parent = obj.offsetParent;
	var intOffsetX = obj.offsetTop;

	while (parent) {
		intOffsetX += parent.offsetTop;
		parent = parent.offsetParent;
	}
	return intOffsetX;
}

/*********************************************************************
'***    Function: shows bubble 
'***
'***    Parameters: 
			e - curent event object
			say - html which is displayed in bubble. must be well formed
			pos - where to show bubble. 
				"auto" (default) - calculates best position where to show bubble
				"left" - always shows bubble on left of current object
				"right" - always shows bubble on right of current object
				
'***        
'***    Returns: void
'***    Remarks: none
'***	Use example

		addListener(document.getElementById("t1"), "mouseover", function (e) {showBubble( e, 'this is a test <b>of the Bubble</b>')});
		addListener(document.getElementById("t2"), "mouseover", function (e) {showBubble( e, 'of course, use it <b>carefully!</b></br> here is a <a href=\'/jobseekerx/\'>link</a> to where you want to go')});
		
		or 

		onmouseover="showBubble(event, 'this is a bold test <b>bubble</b>')"
		onmouseover="showBubble(event, 'this is a bold test <b>bubble</b>', 'right')"

'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 5/26/09
'*********************************************************************/
function showBubble( e, say, pos ) {
    var nav = navigator.userAgent;
    var isOldIE = (nav.indexOf("MSIE") >= 0 && nav.indexOf("MSIE 8") == -1);

    if (pos == null)
        pos = "auto"; // default value of param

    var hint = document.getElementById("bubbleHint");
    var hintText = document.getElementById("bubbleText");
    var hintClass = "hint";


    var obj = getEventSource(e);
    var styleLeft = e.clientX;
    var styleTop = e.clientY;
    var intOffsetWidth = obj.offsetWidth;
    var intClientWidth = obj.clientWidth;
    if (isOldIE) // old ie uses OffsetWidth instead
        intClientWidth = intOffsetWidth;

    // get offsetX (ff does not support, calculate for it)
    var intOffsetX = 0;
    if (typeof (e.offsetX) == "number")
        intOffsetX = e.offsetX;
    else
        intOffsetX = getOffsetX(obj, e);

	// page scroll fix
	var shiftTop  = 0;
	var shiftLeft = 0;
    
    var htmlObj = document.getElementsByTagName("html")[0];
    if (nav.indexOf("Gecko") >=0) // Gecko based browsers use body instead
		htmlObj = document.getElementsByTagName("body")[0];
    
    if (htmlObj != null) {
	    shiftTop = htmlObj.scrollTop;
		shiftLeft = htmlObj.scrollLeft;
	}

    // calc position if auto
    if (pos == "auto")
        pos = intOffsetX < intClientWidth / 2 ? "left" : "right";

    var shift = intOffsetWidth - intOffsetX;
    if (pos == "right") {
        styleLeft = styleLeft + 10 + shift + shiftLeft + "px";
        styleTop = styleTop - 10 + shiftTop + "px";
    }
    else { // left
        styleLeft = styleLeft - (10 + hint.offsetWidth + intClientWidth) + shiftLeft + shift + "px";
        styleTop = styleTop - 10 + shiftTop + "px";
        hintClass = "hint left";
    }

    // must change display for offset properties to work
    hint.className = hintClass;
    hint.style.position = "absolute";
    hint.style.left = -2000; // hide hint

    // position and show hint	
    hintText.innerHTML = say;
    hint.style.left = styleLeft;
    hint.style.top = styleTop;
    hint.style.display = "block";
    return; 
}
// always shows bubble on left
function showBubbleOnLeft( e, say ) {
	return showBubble(e, say, "left");
}
// always shows bubble on right
function showBubbleOnRight( e, say ) {
	return showBubble(e, say, "right");
}
// hides bubble
function hideBubble() {
	var hint = document.getElementById("bubbleHint");
	hint.style.display = "none";
}

/*********************************************************************
'***    Function: shows bubble 
'***
'***    Parameters: 
        e - curent event object
        url - url to request with ajax call
        pos - where to show bubble. 
        "auto" (default) - calculates best position where to show bubble
        "left" - always shows bubble on left of current object
        "right" - always shows bubble on right of current object

'***    Returns: void
'***    Remarks: none
'***	Use example

addListener(document.getElementById("t1"), "mouseover", function (e) {showBubbleAjax( e, '/Components/SomeComponent.asp')});

'***    Created by: dimab
'***    Changed by: dimab
'***    Last change: 6/10/09
'*********************************************************************/
function showBubbleAjax(e, url, pos) {
    showBubble(e, "<div class='loading'></div>", pos);
    AjaxGet(url, "bubbleText", "failed to retrieve data...");
}
function showBubbleAjaxRight(e, url) {
    return showBubbleAjax(e, url, "right");
}
function showBubbleAjaxLeft(e, url) {
    return showBubbleAjax(e, url, "left");
}


// add call to onload event
addLoadEvent(prepareAllInputsForHints);

