
/* common.js */

/* Detect browser name and version */
var agt=navigator.userAgent.toLowerCase();
var appVer = navigator.appVersion.toLowerCase();
var is_minor = parseFloat(appVer);
var is_major = parseInt(is_minor);
var iePos = appVer.indexOf('msie');
if (iePos !=-1) {
    is_minor = parseFloat(appVer.substring(iePos+5,appVer.indexOf(';',iePos)))
    is_major = parseInt(is_minor);
}
var is_ie = ((iePos!=-1));
var is_ie6down = (is_ie && is_minor <= 6);

function ietruebody(){
    return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

// allows multiple functions attached to the window.onload event
if ( typeof( addLoadEvent ) == "undefined" ) {
	function addLoadEvent(f) { var old = window.onload; if (typeof window.onload != 'function') { window.onload = f; } else { window.onload = function onloadHandler() { old(); f();} } }
}

function complaceo_addUnloadEvent(f) 
{ 
	var old = window.onunload; 
	if (typeof old != 'function') 
	{ 
		window.onunload = f; 
	}
	else 
	{ 
		//window.onunload = function onunloadHandler() { old(); f();} };
		window.onunload = function()
		{
			old();
			f();
		}
	}
}


function complaceo_GetObject( o )
{
	if (document.all)
		return document.all[o];
	else
		return document.getElementById(o);
}

// runs scripting when the DOM is ready, instead of when the page is ready
function init() {
	// quit if this function has already been called
	if (arguments.callee.done) return;

	// flag this function so we don't do the same thing twice
	arguments.callee.done = true;
	oGod.mInit();
};

// for Mozilla (IE's eventlistener is set through the htc)
if (document.addEventListener) { document.addEventListener("DOMContentLoaded", init, null); }
// for other browsers
addLoadEvent( init );


// main object for controlling behaviour
var oGod = new cGod();
function cGod(){
	var self = this;
	var DUMMY_LINK = "javascript:void(false);";
	var oWaitMessage;
	this.oWaitMessage = oWaitMessage;
	
	
	var scrollElement = "";
	this.scrollElement = scrollElement;
	
	// init is run as soon as the DOM is ready
	this.mInit = function mInit(){
		mShowWaitMessage();
		mKillFrames();
		mSetHeight();
		window.onresize = mSetHeight;
	};

	// load is run as soon as the entire document is ready, including images
	this.mLoad = function mLoad(){
		//mFixLinks();
		// attach the new link resolver, replacing mFixLinks, which is slow when there's lot's of links
//		Event.observe( document.body, "click", mLinkResolver );
        jQuery( "body" ).click( mLinkResolver );
		fAssignCapsCheck();
//		mCreateDraggables();
		
		// mScrollIntoView must appear last, or at least very late
		mScrollIntoView();
		
		// Added by RP / Morgan to fix popperIframe problem in the Safari browser on Mac
		var oPopperIframe = jQuery( "#popperIframe" )[ 0 ];
		if (oPopperIframe)  {
		    oPopperIframe.style.position = "absolute";
		}
	};
	
	function mScrollIntoView(){
		if ( self.scrollElement && self.scrollElement != "" ){
			var oItem = $( self.scrollElement );
			if ( oItem && oItem.scrollIntoView ) {
				var oActiveElement;
				if ( document.activeElement ) { oActiveElement = document.activeElement; }
				oItem.scrollIntoView();
				// return focus to the element that had focus before we started our scrolling adventure
				if ( oActiveElement ) { oActiveElement.focus(); }
			}
		}
	}
	
//	function mCreateDraggables(){
//	    // set a timeout to avoid slowdowns due to calling getStyle before page has finished rendering
//	    window.setTimeout( function() {
//	        if ( typeof( Draggable ) != "undefined" ) {
//	            var popperIframe = jQuery( "#popperIframe" )[ 0 ];
//	            if ( popperIframe ) { 
//	                new Draggable( popperIframe, {revert:false, starteffect:null, endeffect:null } );
//                }
//                var helperIframe = jQuery( "#helperIframe" )[ 0 ];
//	            if ( helperIframe ) {
//	                new Draggable( helperIframe, {revert:false, starteffect:null, endeffect:null } );
//	            }
//            }
//	    }, 50);
//	}

	function mShowWaitMessage(){
		// make sure this only get's activated once
		if ( !self.oWaitMessage ) {
			self.oWaitMessage = new Object();
			self.oWaitMessage.div = jQuery( "#waitMsg" )[ 0 ];
			self.oWaitMessage.span = jQuery( "#waitMsgIndicator" )[ 0 ];
			if ( !self.oWaitMessage.div || !self.oWaitMessage.span ) {
				self.oWaitMessage = null;
				return;
			}
			
			// create iframe that prevents IE's bleeding bug
			// TODO: find a more elegant way of finding out if the browser is less than IE7
			 /*@cc_on @*/
            /*@if (@_win32)
                var agt=navigator.userAgent.toLowerCase();
                var appVer = navigator.appVersion.toLowerCase();
                var is_minor = parseFloat(appVer);
                var is_major = parseInt(is_minor);
                var iePos = appVer.indexOf('msie');
                if (iePos !=-1) {
                    is_minor = parseFloat(appVer.substring(iePos+5,appVer.indexOf(';',iePos)))
                    is_major = parseInt(is_minor);
                }
                var is_ie = ((iePos!=-1));
                var is_ie6down = (is_ie && is_minor <= 6);
            
			    if ( is_ie6down && !self.oWaitMessage.div.getElementsByTagName( "iframe" )[0] ){
				    self.oWaitMessage.div.innerHTML = '<iframe class="bleedMat" src="about:blank" scrolling="no" frameborder="0"></iframe>' + self.oWaitMessage.div.innerHTML;
				    var ieMat = self.oWaitMessage.div.firstChild;
				    ieMat.style.width = self.oWaitMessage.div.offsetWidth + "px";
				    ieMat.style.height = self.oWaitMessage.div.offsetHeight + "px";			
			    }
            /*@end @*/
			
			self.oWaitMessage.count = 2;
		
			self.oWaitMessage.tick = function waitTimer_Handler() {
				if ( oGod.oWaitMessage && oGod.oWaitMessage.count > 0  ) {
					oGod.oWaitMessage.count--;
					//oGod.oWaitMessage.span.innerHTML = oGod.oWaitMessage.count;
				} else { 
					oGod.mHideWaitMessage();
				}
			};
			oGod.oWaitMessage.id = window.setInterval( oGod.oWaitMessage.tick, 1000 );			
			self.oWaitMessage.div.style.display = "block";
		}
		
	}
	this.mShowWaitMessage = mShowWaitMessage;
	
	function mHideWaitMessage(){
		if ( self.oWaitMessage ) {
			window.clearInterval( self.oWaitMessage.id );
			self.oWaitMessage.div.style.display = "none";
			self.oWaitMessage = null;
		}
	}
	this.mHideWaitMessage = mHideWaitMessage;
	

	// Sets the height of the main content area
	function mSetHeight() {
		var oMenuBar = jQuery( "#menubar" )[ 0 ];
		var oContentWrapper = jQuery( "#content_wrapper" )[ 0 ];
		var oContent = jQuery( "#content" )[ 0 ];
		var oBottomWrapper = jQuery( "#bottomBanner_wrapper" )[ 0 ];
		var oFullContent = jQuery( "#fullContentWidth" )[ 0 ];
		
		// Set height
		var iTopAndBottomHeight = 89 + 34; // Set this to the total height of the topbar(s) and bottombar(s)
		var x,y;
		if (window.innerHeight) { // all except Explorer
			x = window.innerWidth;
			y = window.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}
		var newHeight = y - iTopAndBottomHeight;
		if (newHeight < 0)
			newHeight = 0;

		if ( oContentWrapper ) {
		
			oMenuBar.style.height = newHeight + "px";
			if (oBottomWrapper)
				iTopAndBottomHeight += 60;
			iTopAndBottomHeight += 48; // Padding
			newHeight = y - iTopAndBottomHeight;
			if (newHeight < 0)
				newHeight = 0;
			oContent.style.height = newHeight + "px";			
		}
		
		if (oFullContent)
		{
			iTopAndBottomHeight += 14; // Padding
			newHeight = y - iTopAndBottomHeight;
			oMenuBar.style.height = newHeight + "px";
			oFullContent.style.height = newHeight + "px";
		}
			
//			var newWidth = x - 165;
//			if (newWidth < 20)
//				newWidth = 0;								
//			else if (newWidth > 450)
//				newWidth = 450;
//			else
//				newWidth = newWidth - 20;
//			oContentWrapper.style.width = newWidth + "px";

	}
	
	// Gets how many pixels the window has been scrolled down
	this.get_ScrollYPosition = function get_ScrollYPosition()
	{
	    return is_ie? ietruebody().scrollTop : window.pageYOffset;
	}
	
	// Gets the height of the main content area
	this.get_WindowHeight = function get_WindowHeight()
	{
	    if (window.innerHeight)
	        // all except Explorer
	        return window.innerHeight;
	    else if (document.documentElement && document.documentElement.clientHeight)
	        // Explorer 6 Strict Mode
	        return document.documentElement.clientHeight;   
	    else if (document.body)
	        // other Explorers
	        return document.body.clientHeight
	    else
	        return -1;
	}
	
	// Gets the width of the main content area
	this.get_WindowWidth = function get_WindowWidth()
	{
	    if (window.innerWidth)
	        // all except Explorer
	        return window.innerWidth;
	    else if (document.documentElement && document.documentElement.clientWidth)
	        // Explorer 6 Strict Mode
	        return document.documentElement.clientWidth;   
	    else if (document.body)
	        // other Explorers
	        return document.body.clientWidth
	    else
	        return -1;
	}	
	
    this.mOpenPopperIframe = function mOpenPopperIframe( href )
    {
        //document.body.scrollIntoView();
        var top = this.get_ScrollYPosition();        
	
        var oContainer = jQuery( "#popperIframe" )[ 0 ];
        oContainer.style.top = top + 100 + "px"
        oContainer.style.display = "block";
        var oClose = jQuery( "#btnClose" )[ 0 ];
        oClose.onclick = function CloseOnClick() {
	        oContainer.style.display = "none";
	        return true;
        }
        var oPopperFrame = jQuery( "#popperFrame" )[ 0 ];
        var oPopperFrameScrolling = jQuery( "#popperFrameScrolling" )[ 0 ];
        if ( false ) // this.rel == "popperIframeWithScrolling" ) {
        {
			if (oPopperFrameScrolling.contentDocument)
			{
				// open followed by close clears existing content.
				oPopperFrameScrolling.contentDocument.open();
				oPopperFrameScrolling.contentDocument.close();
			}
	        oPopperFrame.style.display = "none";
	        oPopperFrameScrolling.style.display = "block";
	        oPopperFrameScrolling.src = href;
        } else {            
			if (oPopperFrame.contentDocument)
			{
				// open followed by close clears existing content.
				oPopperFrame.contentDocument.open();
				oPopperFrame.contentDocument.close();
			}			
	        oPopperFrame.src = href;
	        oPopperFrame.style.display = "block";
	        oPopperFrameScrolling.style.display = "none";
        } 
        oGod.mCloseHelperIframe();
    }
    
	// by declaring the function on this, it becomes public
	this.mClosePopperIframe = function mClosePopperIframe( doPostBack, reloadPage ) {
		mCloseAnyIframe( "popperIframe", "popperFrame", doPostBack, reloadPage, null, null );
	}

	// by declaring the function on this, it becomes public
	this.mClosePopperIframeWithArguments = function mClosePopperIframeWithArguments( eventTarget, eventArgument ) {
		mCloseAnyIframe( "popperIframe", "popperFrame", true, false, eventTarget, eventArgument );
	}

	// by declaring the function on this, it becomes public
	this.mCloseHelperIframe = function mCloseHelperIframe( doPostBack, reloadPage ) {
		mCloseAnyIframe( "helperIframe", "helperFrame", doPostBack, reloadPage, null, null );
	}

	// by declaring the function on this, it becomes public
	function mCloseAnyIframe( sContainerId, sFrameId, doPostBack, reloadPage, postbackEventTarget, postbackEventArgument ) {
		var oContainer = jQuery( "#" + sContainerId )[ 0 ];
		var oFrame = jQuery( "#" + sFrameId )[ 0 ];
		if ( oContainer && oFrame ) {
			oContainer.style.display = "none";
			
			if (oFrame.contentDocument)
			{
				// Open opens a stream for writing new content. 
				// Close forces the document to render. This effectively
				// clears the iFrame before showing (otherwise old
				// content may appear if another iFrame has been opened)
				oFrame.contentDocument.open();
				oFrame.contentDocument.close();
	        }
			
			oFrame.src = "";
		}
	    if ( doPostBack ) {
		    __doPostBack(postbackEventTarget, postbackEventArgument);
	    } else if ( reloadPage ) {
		    window.location.reload( true );
	    }
        return false;
	}

    // Refresh this page, either by postback, which maintains viewstate, or a reload, which starts everything over
    this.mRefresh = function mRefresh( doPostBack, reloadPage, bCascade ) {
	    if ( doPostBack ) {
		    __doPostBack(null, null);
	    } else if ( reloadPage ) {
	        window.location.reload( true );
	    }
	    if ( window.opener && bCascade ) {
		    window.opener.oGod.mRefresh( doPostBack, reloadPage, bCascade );
	    }
    }
	
	this.mFixIframeScrolling = function mFixIframeScrolling() {
		// only fix this for IE
		if ( !window.innerHeight ) {
			var iFrame = jQuery( "#popperIframe" )[ 0 ];
			if ( iFrame ) {
				iFrame.scrolling = "yes";
			}
		}
	}

	function mKillFrames() {
	    // close frame if opened in frame by another site
	    // only exeception is our own ExternalProfileFrame.aspx (an iframe which we offer other sites use on their sites)
		var ExternalProfileFrame = jQuery( "#ExternalProfileFrame" )[ 0 ];
		if ( !ExternalProfileFrame ) {

            try {
		        if (window.self.location.href != window.top.location.href) {
			        if ( window.top.location.replace ) {
				        window.top.location.replace(window.self.location.href);
			        } else {
				        window.top.location = window.self.location.href;
			        }
		        }
            } catch ( ex ) {
                try {
                    window.top.location = window.self.location.href;
                } catch ( ex2 ) {
                    window.open( window.self.location.href );
                    window.close();
                }
            }			
		}

	}	
	
	
	// Attached to document.body, examines the rel attribute of clicked links, and acts accordingly
	// Replaces mFixLinks
	function mLinkResolver( e ){
//        var origin = Event.element( e );
        var origin = e.target;
        if ( origin.tagName.toLowerCase() == "img" ) { 
            try
            {
                origin = origin.up( "a" );
            }
            catch(err)
            {
            
            }
            
        }
        
        // ps: fix - clicking on any image that was not supposed 
        // to be a link resulted in an js-error
        if (typeof(origin) == "undefined")
            return;
        
        if ( origin.tagName.toLowerCase() == "a" && origin.rel && origin.rel != "" ){
            var rel = String( origin.rel );
            
            switch( rel ) {
                case "popup":
				    window.open ( origin.href, "", "width=450,height=540,scrollbars=yes,resizable=yes" );
				    return false;
                    break;
                case "adminpopup":
       				window.open ( origin.href, "", "width=600,height=540,scrollbars=yes,resizable=yes,top=50,left=50" );
				    return false;
				    break;
				case "adminPopup":
				    window.open ( origin.href, "", "width=1024,height=768,scrollbars=yes,resizable=yes,top=50,left=50" );
				    return false;
				    break;
				case "external":
		            window.open( origin.href );
		            return false;
				    break;
				case "print":
			        origin.href = DUMMY_LINK;
                    window.print();
                    return false;
				    break;
				case "close":
			        origin.href = DUMMY_LINK;
			        window.close(); 
			        return false;
			        break;
			    case "popperIframe":
			    case "popperIframeWithScrolling":
			        // dual iframe thingy, because of scrollbars "feature" in IE
    			    
		            // Since popperIframes position is fixed, this makes sure that it is visible after being triggered by a link
		            // document.body.scrollIntoView();
                    var top = is_ie ? ietruebody().scrollTop : window.pageYOffset;
		                			
			        var oContainer = jQuery( "#popperIframe" )[ 0 ];
			        oContainer.style.top = top + 100 + "px";
			        oContainer.style.display = "block";
			        var oClose = jQuery( "#btnClose" )[ 0 ];
			        oClose.onclick = function CloseOnClick() {
				        oContainer.style.display = "none";
				        return true;
			        }
			        var oPopperFrame = jQuery( "#popperFrame" )[ 0 ];
			        var oPopperFrameScrolling = jQuery( "#popperFrameScrolling" )[ 0 ];
			        if ( this.rel == "popperIframeWithScrolling" ) {
						if (oPopperFrame.contentDocument)
						{
							// open followed by close clears existing content.
							oPopperFrame.contentDocument.open();
							oPopperFrame.contentDocument.close();
						}						
				        oPopperFrame.style.display = "none";
				        oPopperFrameScrolling.style.display = "block";
				        oPopperFrameScrolling.src = origin.href;
			        } else {
						if (oPopperFrame.contentDocument)
						{
							// open followed by close clears existing content.
							oPopperFrame.contentDocument.open();
							oPopperFrame.contentDocument.close();
						}
				        oPopperFrame.src = origin.href;
				        oPopperFrame.style.display = "block";
				        oPopperFrameScrolling.style.display = "none";
			        } 
			        oGod.mCloseHelperIframe();
			        return false;
			        break;
                case "helper":
	                var oContainer = jQuery( "#helperIframe" )[ 0 ];
	                if ( oContainer ) {
	                    oContainer.style.display = "block";
	                }
	                var oClose = jQuery( "#btnHelperClose" )[ 0 ];
	                oClose.onclick = function HelperCloseOnClick() {
	                    oContainer.style.display = "none";
	                    return true;
	                }
	                var oHelperFrame = jQuery( "#helperFrame" )[ 0 ];
	                if ( oHelperFrame ) {
	                    oGod.mClosePopperIframe();
	                    oHelperFrame.style.display = "block";
	                    oHelperFrame.src = origin.href;
	                }
	                return false;
                    break;		        
				case "impersonate": 
			        // Impersonate links must open in the same window
			        if (origin.impersonate) {
			            origin.impersonate.close()
			        }
			        origin.impersonate = window.open ( origin.href, "impersonate", "width=1024,height=768,toolbar=1,resizable=1,directories=0,status=1,menubar=1,scrollbars=1,location=1, top=20, left=20", true );	
			        origin.impersonate.focus();
			        return false;
				    break;
            }
        }
	}
	
	/* REFINE: - Calculate position of windows */
	function mFixLinks() {
		var oLinks = document.getElementsByTagName("a");
		var oLink, i = 0;
		
		// iterate throug all links, and assign behaviour based on values in rel attributes
		while ( oLink = oLinks[i++] ) {
		    var rel = String(oLink.rel);
			if ( rel == "popup" ) {
				oLink.onclick = function PopupOnCLick() {
					window.open ( this.href, "", "width=450,height=540,scrollbars=yes,resizable=yes" );
					return false;
				};
			} else if ( rel == "adminpopup" ) {
				oLink.onclick = function PopupOnCLick() {
					window.open ( this.href, "", "width=600,height=540,scrollbars=yes,resizable=yes" );
					return false;
				};
			} else if ( rel == "external" ) {
				oLink.target = "_blank";
			} else if ( rel == "adminPopup" ) {
				oLink.onclick = function AdminPopupOnClick() {
					window.open ( this.href, "", "width=1024,height=768,scrollbars=yes,resizable=yes" );
					return false;
				};
			} else if ( rel == "print" ) {
				oLink.href = DUMMY_LINK;
				oLink.onclick = function PrintOnClick() {
					window.print();
					return false;
				}
			} else if ( rel == "close" ) {
				oLink.href = DUMMY_LINK;
				oLink.onclick = function CloseOnClick() { 
					window.close(); 
					return false;
				};
			} else if ( rel == "popperIframe" || rel == "popperIframeWithScrolling" ) {
				// dual iframe thingy, because of scrollbars "feature" in IE
				oLink.onclick = function PopperIframeOnClick() {
				
				    // Since popperIframes position is fixed, this makes sure that it is visible after being triggered by a link
				    document.body.scrollIntoView();
				
					var oContainer = jQuery( "#popperIframe" )[ 0 ];
					oContainer.style.display = "block";
					var oClose = jQuery( "#btnClose" )[ 0 ];
					oClose.onclick = function CloseOnClick() {
						oContainer.style.display = "none";
						return true;
					}
					var oPopperFrame = jQuery( "#popperFrame" )[ 0 ];
					var oPopperFrameScrolling = jQuery( "#popperFrameScrolling" )[ 0 ];
					if ( this.rel == "popperIframeWithScrolling" ) {
						oPopperFrame.style.display = "none";
						oPopperFrameScrolling.style.display = "block";
						oPopperFrameScrolling.src = this.href;
					} else {
						oPopperFrame.src = this.href;
						oPopperFrame.style.display = "block";
						oPopperFrameScrolling.style.display = "none";
					} 
					oGod.mCloseHelperIframe();
					return false;
				};
			} else if ( rel == "helper" ) {
			    oLink.onclick = function helperIFrameOnClick() {
			        var oContainer = jQuery( "#helperIframe" )[ 0 ];
			        if ( oContainer ) {
			            oContainer.style.display = "block";
			        }
			        var oClose = jQuery( "#btnHelperClose" )[ 0 ];
			        oClose.onclick = function HelperCloseOnClick() {
			            oContainer.style.display = "none";
			            return true;
			        }
			        var oHelperFrame = jQuery( "#helperFrame" )[ 0 ];
			        if ( oHelperFrame ) {
			            oGod.mClosePopperIframe();
			            oHelperFrame.style.display = "block";
			            oHelperFrame.src = this.href;
			        }
			        return false;
			    };
			} else if ( rel == "impersonate" ) {
				// Impersonate links must open in the same window
				oLink.onclick = function ImpersonateOnClick() {
					if (this.impersonate) {
					    this.impersonate.close()
					}
					this.impersonate = window.open ( this.href, "impersonate", "width=1024,height=768,toolbar=1,resizable=1,directories=0,status=1,menubar=1,scrollbars=1,location=1, top=20, left=20", true );	
					this.impersonate.focus();
					return false;
				};
			}
		}
	}
	
	/**
	    Validates multiple emails, separated by ";"
	*/
	function mValidateMultipleEmail( oInput, xEmail, xWhiteSpace ){	 
	    if ( !oInput || !xEmail || !xWhiteSpace ) { return null; }
	    oInput.value = oInput.value.replace( xWhiteSpace, ";" );
	    oInput.value = oInput.value.replace( /\,/g, ";" );
	    oInput.value = oInput.value.replace( /\;{2,}/g, ";" );
	    var aValues = oInput.value.split( ";" );
	    var aValue, i = 0;
	    var bIsValid = true;
	    while ( aValue = aValues[i++] ) {
		    if ( aValue != ";" ){
			    bIsValid = bIsValid && aValue.match( xEmail );	
		    } 
	    }
	    return bIsValid;
	}
	this.mValidateMultipleEmail = mValidateMultipleEmail;
	
	
	this.mPopulateSkillNames = function mPopulateSkillNames( sName, sAbbriviation, sControlID ) {
	    if ( typeof( PopulateSkillNames ) == "function" ) {
	        return ( PopulateSkillNames( sName, sAbbriviation, sControlID ) );
	    }
	    return false;
	}
	
	function fAssignCapsCheck() {
		var oInputs = document.getElementsByTagName("input");
		var oInput, i = 0;
		while ( oInput = oInputs[i++] ) {
			if ( oInput.className.indexOf( "capsLockOff" ) != -1 ) {
				oInput.onkeypress = function OnKeyPressHandler( e ) {
					if (!e) var e = window.event;
					var myKeyCode=0;
					var myShiftKey=false;

					// Internet Explorer 4+
					if ( document.all ) {
						myKeyCode = e.keyCode;
						myShiftKey = e.shiftKey;
					// Netscape 4
					} else if ( document.layers ) {
						myKeyCode = e.which;
						myShiftKey = ( myKeyCode == 16 ) ? true : false;
					// Netscape 6
					} else if ( document.getElementById ) {
						myKeyCode = e.which;
						myShiftKey = ( myKeyCode == 16 ) ? true : false;
					}
					// Upper case letters are seen without depressing the Shift key, therefore Caps Lock is on
					if ( ( myKeyCode >= 65 && myKeyCode <= 90 ) && !myShiftKey ) {
						this.className = "capsLockOn"
					} else {
						this.className = "capsLockOff"
					}
				}
			}
		}
	}
}

addLoadEvent( oGod.mLoad );

/** sets checked to true for a list of checkboxes */
function checkRest(){
	//get a list of all the input fields to check.
	var checkList = this.checkList.split(",");

	//if we are unchecking then don't check the rest in the list.
	if(this.checked == true){
		for(i = 0; checkList[i] != null; ++i ){
			var oCheckBox = jQuery( "#" + checkList[ i ] )[ 0 ];
			if ( oCheckBox ) {
				oCheckBox.checked = true;
			}
		}
	}
}


addLoadEvent( fIsFormDirty );
function fIsFormDirty(){
	oHidden = jQuery( "#ctl00_FormDirty" )[ 0 ];
	if ( oHidden && ( oHidden.value == "true" || oHidden.value == "True" ) ){ 
		window.isDirty = true;
	}
}

function Complaceo_ShowHide_HeaderToggleState(sender)
{
    var plusMinusDiv = sender;
    var topDiv = sender.parentNode.parentNode;
    var tempThs = plusMinusDiv.getElementsByTagName("tr");
    var openClosedThs = new Array();

    for( var i = 0; i < tempThs.length; i++ )
        if ( tempThs[i].id.indexOf( "uxExpandedHeader" ) > -1 || tempThs[i].id.indexOf( "uxCollapsedHeader" ) > -1 )
            openClosedThs[ openClosedThs.length ] = tempThs[ i ];

    var headerOpen = openClosedThs[0];
    var headerClosed = openClosedThs[1];
    
    var expandedHidden = topDiv.getElementsByTagName("input")[0];

    var contentDiv = complaceo_showHidePanel_GetContentDiv(topDiv);
	jQuery(contentDiv).slideToggle(250);

    if (expandedHidden.value == "True")
    {
        expandedHidden.value = "False";
        headerOpen.style.display = "none";
        headerClosed.style.display = "inline";
    }
    else
    {
        expandedHidden.value = "True";
        headerOpen.style.display = "inline";
        headerClosed.style.display = "none";
    }

    var i=1;
}

function complaceo_showHidePanel_ToggleContent(sender)
{
    var plusMinusDiv = sender;
    var topDiv = sender.parentNode.parentNode;    
	var plusMinusImages = plusMinusDiv.getElementsByTagName("img");
    
    var contentDiv = complaceo_showHidePanel_GetContentDiv(topDiv);
    var expandedHidden = topDiv.getElementsByTagName("input")[0];
    var expanded = expandedHidden.value == "True";
	var expandImg = plusMinusImages[0];
	var collapseImg = plusMinusImages[1];
	

    expandedHidden.value = expanded ? "False" : "True";
    contentDiv.style.display = expanded ? "none" : "";
    
	expandImg.style.display = expanded ? "inline" : "none";
	collapseImg.style.display = expanded ? "none" : "inline";	
}

function complaceo_showHidePanel_GetContentDiv(topDiv)
{
    //var contentDiv = topDiv.getElementsByClassName("content")[0];
    var contentDiv = topDiv.firstChild;
    while(contentDiv && contentDiv.className != "content")
    {
		contentDiv = contentDiv.nextSibling;
    }
    return contentDiv;
}

function complaceo_confirm(text, e)
{
    if (!e)
        var e = window.event
    if (confirm(text))
    {
        return true;
    }
    else
    {
        e.cancelBubble = true;
        if ( e.stopPropagation ) {
		        e.stopPropagation();
        }				
        e.returnValue = false;
        if ( e.preventDefault ) {
	        e.preventDefault();
        }
        return false;
    }
}

/*
Cool DHTML tooltip script- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
This notice MUST stay intact for legal use
Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code

Please note! The original script has been modified to accomodate IT-Jobbanks needs and to fix a few bugs! 
*/

var offsetxpoint=-150 //Customize x offset of tooltip
var offsetypoint=20 //Customize y offset of tooltip
var ie=document.all
var ns6=document.getElementById && !document.all
var enabletip=false

if (ie||ns6)
    var tipobj;
    complaceo_AddLoadEvent( function() {
		tipobj = complaceo_GetObject("tooltip");
	}
);

function complaceo_AddLoadEvent(f)
{
     
	var old = window.onload; 
	
	if (typeof window.onload != 'function') 
		{ window.onload = f; } else { window.onload = function onloadHandler() { old(); f();} } 
}

function complaceo_GetObject( o )
{
	if (document.all)
		return document.all[o];
	else
		return document.getElementById(o);
}

// Attach the hide function to all links with the correct class
// TODO: create a global function, available on window onload, where all links are processed, and send functions to this global function
// addLoadEvent( function() {
//		var oLinks = document.getElementsByTagName( "a" );
//		var oLink, i = 0;
//		while ( oLink = oLinks[i++] ){
//			if ( oLink.className.indexOf( "ddrivetip" ) != -1 ) {
//				oLink.onmouseout = hideddrivetip;
//			}
//		}
//	}
//);

function ddrivetip(parent, thetext, thecolor, thewidth, contentFromTinyMCE) {
    if (ns6||ie) {
        if (typeof thewidth!="undefined" && thewidth!=0) {
            tipobj.style.width=thewidth+"px"
        }
        
        if (typeof thecolor!="undefined" && thecolor!="" && thecolor!=0 && thecolor!=null) {
            tipobj.style.backgroundColor=thecolor
        }

        if (typeof contentFromTinyMCE!="undefined" && contentFromTinyMCE!="" && contentFromTinyMCE!=0) {
            tipobj.setAttribute("class", "ContentFromTinyMCE ToolTipWithContentFromTinyMCE");
        }
        
        tipobj.innerHTML=thetext
        enabletip=true
        
        // create iframe that prevents IE 6's bleeding bug
        if ( is_ie6down && !tipobj.getElementsByTagName( "iframe" )[0] ){
            tipobj.innerHTML = '<iframe class="bleedMat" src="about:blank" scrolling="no" frameborder="0"></iframe>' + tipobj.innerHTML;
            var ieMat = tipobj.firstChild;
            ieMat.style.width = tipobj.offsetWidth + "px";
            ieMat.style.height = tipobj.offsetHeight + "px";			
        }
        parent.onmousemove = positionddrivetip;
        return false
    }    
}

function positionddrivetip(e){
    if (enabletip){
        var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft;
        var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop;
        
        //Find out how close the mouse is to the corner of the window
        var rightedge=ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20
        var bottomedge=ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20

        var leftedge=(offsetxpoint<0)? offsetxpoint*(-1) : -1000

        //if the horizontal distance isn't enough to accomodate the width of the context menu
        if (rightedge<tipobj.offsetWidth)
        {
            //move the horizontal position of the menu to the left by it's width
            var left = ie? ietruebody().scrollLeft+event.clientX-tipobj.offsetWidth : window.pageXOffset+e.clientX-tipobj.offsetWidth
            if (left < 5)
                left = 5
            tipobj.style.left= left + "px"
        }
        else if (curX<leftedge)
            tipobj.style.left="5px"
        else
            //position the horizontal position of the menu where the mouse is positioned
            tipobj.style.left=curX+offsetxpoint+"px"

        //same concept with the vertical position
        if (bottomedge<tipobj.offsetHeight)
        {
            var top = ie? ietruebody().scrollTop+event.clientY-tipobj.offsetHeight-offsetypoint : window.pageYOffset+e.clientY-tipobj.offsetHeight-offsetypoint
            if ( top < 0 )
            {
                // The tooltip is higher than the available size. Place the 
                // tooltip under the parent and resize it to fit the entire
                // witch of the screen.
                top = curY+offsetypoint
                tipobj.style.left = "5px"
                var width = ie&&!window.opera? ietruebody().clientWidth : window.innerWidth
                width = width - 40;
                tipobj.style.width = width+"px"
            }
            tipobj.style.top= top +"px" 
        }
        else
            tipobj.style.top=curY+offsetypoint+"px"
        tipobj.style.visibility="visible"
    }
}

function hideddrivetip(parent){
    if (ns6||ie){
        enabletip=false
        tipobj.style.visibility="hidden"
        tipobj.style.left="-1000px"
        tipobj.style.backgroundColor=''
        tipobj.style.width=''
    }
    parent.onmousemove = null;
}

//document.onmousemove=positionddrivetip

/*
 * jQuery blockUI plugin
 * Version 2.18 (29-APR-2009)
 * @requires jQuery v1.2.3 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2008 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */

;(function($) {

if (/1\.(0|1|2)\.(0|1|2)/.test(jQuery.fn.jquery) || /^1.1/.test(jQuery.fn.jquery)) {
    alert('blockUI requires jQuery v1.2.3 or later!  You are using v' + jQuery.fn.jquery);
    return;
}

jQuery.fn._fadeIn = jQuery.fn.fadeIn;

var setExpr = (function() {
	if (!jQuery.browser.msie) return false;
    var div = document.createElement('div');
    try { div.style.setExpression('width','0+0'); }
    catch(e) { return false; }
    return true;
})();


// global $ methods for blocking/unblocking the entire page
jQuery.blockUI   = function(opts) { install(window, opts); };
jQuery.unblockUI = function(opts) { remove(window, opts); };

// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
jQuery.growlUI = function(title, message, timeout) {
	var $m = jQuery('<div class="growlUI"></div>');
	if (title) $m.append('<h1>'+title+'</h1>');
	if (message) $m.append('<h2>'+message+'</h2>');
	if (timeout == undefined) timeout = 3000;
    jQuery.blockUI({
		message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
		timeout: timeout, showOverlay: false,
		css: jQuery.blockUI.defaults.growlCSS
    });
};

// plugin method for blocking element content
jQuery.fn.block = function(opts) {
    return this.unblock({ fadeOut: 0 }).each(function() {
        if (jQuery.css(this,'position') == 'static')
            this.style.position = 'relative';
        if (jQuery.browser.msie)
            this.style.zoom = 1; // force 'hasLayout'
        install(this, opts);
    });
};

// plugin method for unblocking element content
jQuery.fn.unblock = function(opts) {
    return this.each(function() {
        remove(this, opts);
    });
};

jQuery.blockUI.version = 2.18; // 2nd generation blocking at no extra cost!

// override these in your code to change the default behavior and style
jQuery.blockUI.defaults = {
    // message displayed when blocking (use null for no message)
    message:  '<h1>Please wait...</h1>',

    // styles for the message when blocking; if you wish to disable
    // these and use an external stylesheet then do this in your code:
    // jQuery.blockUI.defaults.css = {};
    css: {
        padding:        0,
        margin:         0,
        width:          '30%',
        top:            '40%',
        left:           '35%',
        textAlign:      'center',
        color:          '#000',
        border:         '3px solid #aaa',
        backgroundColor:'#fff',
        cursor:         'wait'
    },

    // styles for the overlay
    overlayCSS:  {
        backgroundColor: '#000',
        opacity:         '0.6'
    },

	// styles applied when using jQuery.growlUI
	growlCSS: {
		width:    '350px',
		top:      '10px',
		left:     '',
		right:    '10px',
	    border:   'none',
	    padding:  '5px',
	    opacity:  '0.6',
		cursor:    null,
	    color:    '#fff',
	    backgroundColor: '#000',
	    '-webkit-border-radius': '10px',
	    '-moz-border-radius':    '10px'
	},
	
	// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
	// (hat tip to Jorge H. N. de Vasconcelos)
	iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',

	// force usage of iframe in non-IE browsers (handy for blocking applets)
	forceIframe: false,

    // z-index for the blocking overlay
    baseZ: 1000,

    // set these to true to have the message automatically centered
    centerX: true, // <-- only effects element blocking (page block controlled via css above)
    centerY: true,

    // allow body element to be stetched in ie6; this makes blocking look better
    // on "short" pages.  disable if you wish to prevent changes to the body height
    allowBodyStretch: true,

	// enable if you want key and mouse events to be disabled for content that is blocked
	bindEvents: true,

    // be default blockUI will supress tab navigation from leaving blocking content
    // (if bindEvents is true)
    constrainTabKey: true,

    // fadeIn time in millis; set to 0 to disable fadeIn on block
    fadeIn:  200,

    // fadeOut time in millis; set to 0 to disable fadeOut on unblock
    fadeOut:  400,

	// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
	timeout: 0,

	// disable if you don't want to show the overlay
	showOverlay: true,

    // if true, focus will be placed in the first available input field when
    // page blocking
    focusInput: true,

    // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
    applyPlatformOpacityRules: true,

    // callback method invoked when unblocking has completed; the callback is
    // passed the element that has been unblocked (which is the window object for page
    // blocks) and the options that were passed to the unblock call:
    //     onUnblock(element, options)
    onUnblock: null,

    // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
    quirksmodeOffsetHack: 4
};

// private data and functions follow...

var ie6 = jQuery.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
var pageBlock = null;
var pageBlockEls = [];

function install(el, opts) {
    var full = (el == window);
    var msg = opts && opts.message !== undefined ? opts.message : undefined;
    opts = jQuery.extend({}, jQuery.blockUI.defaults, opts || {});
    opts.overlayCSS = jQuery.extend({}, jQuery.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
    var css = jQuery.extend({}, jQuery.blockUI.defaults.css, opts.css || {});
    msg = msg === undefined ? opts.message : msg;

    // remove the current block (if there is one)
    if (full && pageBlock)
        remove(window, {fadeOut:0});

    // if an existing element is being used as the blocking content then we capture
    // its current place in the DOM (and current display style) so we can restore
    // it when we unblock
    if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
        var node = msg.jquery ? msg[0] : msg;
        var data = {};
        jQuery(el).data('blockUI.history', data);
        data.el = node;
        data.parent = node.parentNode;
        data.display = node.style.display;
        data.position = node.style.position;
		if (data.parent)
			data.parent.removeChild(node);
    }

    var z = opts.baseZ;

    // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
    // layer1 is the iframe layer which is used to supress bleed through of underlying content
    // layer2 is the overlay layer which has opacity and a wait cursor
    // layer3 is the message content that is displayed while blocking

    var lyr1 = (jQuery.browser.msie || opts.forceIframe) 
    	? jQuery('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
        : jQuery('<div class="blockUI" style="display:none"></div>');
    var lyr2 = jQuery('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
    var lyr3 = full ? jQuery('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
                    : jQuery('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute;"></div>');

    // if we have a message, style it
    if (msg)
        lyr3.css(css);

    // style the overlay
    if (!opts.applyPlatformOpacityRules || !(jQuery.browser.mozilla && /Linux/.test(navigator.platform)))
        lyr2.css(opts.overlayCSS);
    lyr2.css('position', full ? 'fixed' : 'absolute');
    
    if ( !full && opts.borderRadius )
    {
        lyr2.css('-webkit-border-radius', opts.borderRadius + 'px');
        lyr2.css('-moz-border-radius', opts.borderRadius + 'px');
    }

    // make iframe layer transparent in IE
    if (jQuery.browser.msie || opts.forceIframe)
        lyr1.css('opacity','0.0');

    jQuery([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);

    // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
    var expr = jQuery.browser.msie && (jQuery.browser.version < 8 || !jQuery.boxModel) && (!jQuery.boxModel || jQuery('object,embed', full ? null : el).length > 0);
    if (ie6 || (expr && setExpr)) {
        // give body 100% height
        if (full && opts.allowBodyStretch && jQuery.boxModel)
            jQuery('html,body').css('height','100%');

        // fix ie6 issue when blocked element has a border width
        if ((ie6 || !jQuery.boxModel) && !full) {
            var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
            var fixT = t ? '(0 - '+t+')' : 0;
            var fixL = l ? '(0 - '+l+')' : 0;
        }

        // simulate fixed position
        jQuery.each([lyr1,lyr2,lyr3], function(i,o) {
            var s = o[0].style;
            s.position = 'absolute';
            if (i < 2) {
                full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
                     : s.setExpression('height','this.parentNode.offsetHeight + "px"');
                full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
                     : s.setExpression('width','this.parentNode.offsetWidth + "px"');
                if (fixL) s.setExpression('left', fixL);
                if (fixT) s.setExpression('top', fixT);
            }
            else if (opts.centerY) {
                if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
                s.marginTop = 0;
            }
			else if (!opts.centerY && full) {
				var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
				var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
                s.setExpression('top',expression);
			}
        });
    }

    // show the message
	if (msg) {
		lyr3.append(msg);
		if (msg.jquery || msg.nodeType)
			jQuery(msg).show();
	}

	if ((jQuery.browser.msie || opts.forceIframe) && opts.showOverlay)
		lyr1.show(); // opacity is zero
	if (opts.fadeIn) {
		if (opts.showOverlay)
			lyr2._fadeIn(opts.fadeIn);
		if (msg)
			lyr3.fadeIn(opts.fadeIn);
	}
	else {
		if (opts.showOverlay)
			lyr2.show();
		if (msg)
			lyr3.show();
	}

    // bind key and mouse events
    bind(1, el, opts);

    if (full) {
        pageBlock = lyr3[0];
        pageBlockEls = jQuery(':input:enabled:visible',pageBlock);
        if (opts.focusInput)
            setTimeout(focus, 20);
    }
    else
        center(lyr3[0], opts.centerX, opts.centerY);

	if (opts.timeout) {
		// auto-unblock
		var to = setTimeout(function() {
			full ? jQuery.unblockUI(opts) : jQuery(el).unblock(opts);
		}, opts.timeout);
		jQuery(el).data('blockUI.timeout', to);
	}
};

// remove the block
function remove(el, opts) {
    var full = el == window;
	var $el = jQuery(el);
    var data = $el.data('blockUI.history');
	var to = $el.data('blockUI.timeout');
	if (to) {
		clearTimeout(to);
		$el.removeData('blockUI.timeout');
	}
    opts = jQuery.extend({}, jQuery.blockUI.defaults, opts || {});
    bind(0, el, opts); // unbind events
    var els = full ? jQuery('body').children().filter('.blockUI') : jQuery('.blockUI', el);

    if (full)
        pageBlock = pageBlockEls = null;

    if (opts.fadeOut) {
        els.fadeOut(opts.fadeOut);
        setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
    }
    else
        reset(els, data, opts, el);
};

// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
    els.each(function(i,o) {
        // remove via DOM calls so we don't lose event handlers
        if (this.parentNode)
            this.parentNode.removeChild(this);
    });

    if (data && data.el) {
        data.el.style.display = data.display;
        data.el.style.position = data.position;
		if (data.parent)
			data.parent.appendChild(data.el);
        jQuery(data.el).removeData('blockUI.history');
    }

    if (typeof opts.onUnblock == 'function')
        opts.onUnblock(el,opts);
};

// bind/unbind the handler
function bind(b, el, opts) {
    var full = el == window, $el = jQuery(el);

    // don't bother unbinding if there is nothing to unbind
    if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
        return;
    if (!full)
        $el.data('blockUI.isBlocked', b);

	// don't bind events when overlay is not in use or if bindEvents is false
    if (!opts.bindEvents || (b && !opts.showOverlay)) 
		return;

    // bind anchors and inputs for mouse and key events
    var events = 'mousedown mouseup keydown keypress';
    b ? jQuery(document).bind(events, opts, handler) : jQuery(document).unbind(events, handler);

// former impl...
//    var $e = jQuery('a,:input');
//    b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
};

// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
    // allow tab navigation (conditionally)
    if (e.keyCode && e.keyCode == 9) {
        if (pageBlock && e.data.constrainTabKey) {
            var els = pageBlockEls;
            var fwd = !e.shiftKey && e.target == els[els.length-1];
            var back = e.shiftKey && e.target == els[0];
            if (fwd || back) {
                setTimeout(function(){focus(back)},10);
                return false;
            }
        }
    }
    // allow events within the message content
    if (jQuery(e.target).parents('div.blockMsg').length > 0)
        return true;

    // allow events for content that is not being blocked
    return jQuery(e.target).parents().children().filter('div.blockUI').length == 0;
};

function focus(back) {
    if (!pageBlockEls)
        return;
    var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
    if (e)
        e.focus();
};

function center(el, x, y) {
    var p = el.parentNode, s = el.style;
    var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
    var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
    if (x) s.left = l > 0 ? (l+'px') : '0';
    if (y) s.top  = t > 0 ? (t+'px') : '0';
};

function sz(el, p) {
    return parseInt(jQuery.css(el,p))||0;
};

})(jQuery);
(function(jQuery){

	jQuery.fn.alphanumeric = function(p) { 

		p = jQuery.extend({
			ichars: "!@#$%^&*()+=[]\\\';,/{}|\":<>?~`.- ",
			nchars: "",
			allow: ""
		  }, p);	

		return this.each
			(
				function() 
				{

					if (p.nocaps) p.nchars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
					if (p.allcaps) p.nchars += "abcdefghijklmnopqrstuvwxyz";
					
					s = p.allow.split('');
					for ( i=0;i<s.length;i++) if (p.ichars.indexOf(s[i]) != -1) s[i] = "\\" + s[i];
					p.allow = s.join('|');
					
					var reg = new RegExp(p.allow,'gi');
					var ch = p.ichars + p.nchars;
					ch = ch.replace(reg,'');

					jQuery(this).keypress
						(
							function (e)
								{
								
									if (!e.charCode) k = String.fromCharCode(e.which);
										else k = String.fromCharCode(e.charCode);
										
									if (ch.indexOf(k) != -1) e.preventDefault();
									if (e.ctrlKey&&k=='v') e.preventDefault();
									
								}
								
						);
						
					jQuery(this).bind('contextmenu',function () {return false});
									
				}
			);

	};

	jQuery.fn.numeric = function(p) {
	
		var az = "abcdefghijklmnopqrstuvwxyz";
		az += az.toUpperCase();

		p = jQuery.extend({
			nchars: az
		  }, p);	
		  	
		return this.each (function()
			{
				jQuery(this).alphanumeric(p);
			}
		);
			
	};
	
	jQuery.fn.alpha = function(p) {

		var nm = "1234567890";

		p = jQuery.extend({
			nchars: nm
		  }, p);	

		return this.each (function()
			{
				jQuery(this).alphanumeric(p);
			}
		);
			
	};	

})(jQuery);
/* Copyright (c) 2006-2007 Mathias Bank (http://www.mathias-bank.de)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * 
 * Version 2.1
 * 
 * Thanks to 
 * Hinnerk Ruemenapf - http://hinnerk.ruemenapf.de/ for bug reporting and fixing.
 * Tom Leonard for some improvements
 * 
 */
function URLEncode(unencodedValue )
{
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var plaintext = unencodedValue;
	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
};

function URLDecode(encodedValue)
{
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var encoded = encodedValue
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				alert( 'Bad escape combination near ...' + encoded.substr(i) );
				plaintext += "%[ERROR]";
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	} // while
   return plaintext;
};
 
jQuery.fn.extend({
/**
* Returns get parameters.
*
* If the desired param does not exist, null will be returned
*
* To get the document params:
* @example value = jQuery(document).getUrlParam("paramName");
* 
* To get the params of a html-attribut (uses src attribute)
* @example value = jQuery('#imgLink').getUrlParam("paramName");
*/ 
 getUrlParam: function(strParamName){
	  strParamName = escape(unescape(strParamName));
	  
	  var returnVal = new Array();
	  var qString = null;
	  
	  if (jQuery(this).attr("nodeName")=="#document") {
	  	//document-handler
		
		if (window.location.search.search(strParamName) > -1 ){
			
			qString = window.location.search.substr(1,window.location.search.length).split("&");
		}
			
	  } else if (jQuery(this).attr("src")!="undefined") {
	  	
	  	var strHref = jQuery(this).attr("src")
	  	if ( strHref.indexOf("?") > -1 ){
	    	var strQueryString = strHref.substr(strHref.indexOf("?")+1);
	  		qString = strQueryString.split("&");
	  	}
	  } else if (jQuery(this).attr("href")!="undefined") {
	  	
	  	var strHref = jQuery(this).attr("href")
	  	if ( strHref.indexOf("?") > -1 ){
	    	var strQueryString = strHref.substr(strHref.indexOf("?")+1);
	  		qString = strQueryString.split("&");
	  	}
	  } else {
	  	return null;
	  }
	  	
	  
	  if (qString==null) return null;
	  
	  
	  for (var i=0;i<qString.length; i++){
			if (escape(unescape(qString[i].split("=")[0])) == strParamName){
				returnVal.push(qString[i].split("=")[1]);
			}
			
	  }
	  
	  
	  if (returnVal.length==0) return null;
	  else if (returnVal.length==1) return returnVal[0];
	  else return returnVal;
	}
});
function boxAutocomplete()
{
	jQuery(".box.autocomplete").wrapInner('<div class="content"></div>').prepend('	<div class="corners"><div class="topmiddle">&nbsp;</div> <div class="topleft">&nbsp;</div>	<div class="topright">&nbsp;</div>	<div class="bottomleft">&nbsp;</div>  <div class="bottommiddle">&nbsp;</div>		<div class="bottomright">&nbsp;</div>	</div><div class="boxTopSpacer">&nbsp</div>').append('<div class="boxBottomSpacer">&nbsp</div>');
}

jQuery(document).ready( boxAutocomplete );
/*-------------------------------------------------------------------- 
Scripts for creating and manipulating custom menus based on standard <ul> markup
Version: 3.0, 03.31.2009

By: Maggie Costello Wachs (maggie@filamentgroup.com) and Scott Jehl (scott@filamentgroup.com)
	http://www.filamentgroup.com
	* reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/
		
Copyright (c) 2009 Filament Group
Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
--------------------------------------------------------------------*/


var allUIMenus = [];

jQuery.fn.menu = function(options){
	var caller = this;
	var options = options;
	var m = new Menu(caller, options);	
	allUIMenus.push(m);
	
	
	jQuery(this).mousedown(function(){
		if (!m.menuOpen) { m.showLoading(); };
	});
    jQuery(this).hover(function(){
        if (m.menuOpen == false) { m.showMenu(); }
        else { m.kill(); };
        return false;
    });
};

function Menu(caller, options){
	var menu = this;
	var caller = jQuery(caller);
	var container = jQuery('<div class="fg-menu-container ui-widget ui-widget-content ui-corner-all">'+options.content+'</div>');
	
	this.menuOpen = false;
	this.menuExists = false;
	
	var options = jQuery.extend({
		content: null,
		width: 180, // width of menu container, must be set or passed in to calculate widths of child menus
		maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb)
		positionOpts: {
			posX: 'left', 
			posY: 'bottom',
			offsetX: 0,
			offsetY: 0,
			directionH: 'right',
			directionV: 'down', 
			detectH: true, // do horizontal collision detection  
			detectV: true, // do vertical collision detection
			linkToFront: false
		},
		showSpeed: 200, // show/hide speed in milliseconds
		callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing
		loadingState: 'ui-state-loading', // class added to the link/button while the menu is created
		linkHover: 'ui-state-hover', // class for menu option hover state
		linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus		
	// ----- multi-level menu defaults -----
		crossSpeed: 200, // cross-fade speed for multi-level menus
		crumbDefaultText: 'Choose an option:',
		backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link
		backLinkText: 'Back',
		flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead
		flyOutOnState: 'ui-state-default',
		nextMenuLink: 'ui-icon-triangle-1-e', // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level
		topLinkText: 'All',
		nextCrumbLink: 'ui-icon-carat-1-e'	
	}, options);
	
	var killAllMenus = function(){
		jQuery.each(allUIMenus, function(i){
			if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); };	
		});
	};
	
	this.kill = function(){
		caller
			.removeClass(options.loadingState)
			.removeClass('fg-menu-open')
			.removeClass(options.callerOnState);	
		container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover);		
		if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); };	
		if (options.callerOnState) { 	caller.removeClass(options.callerOnState); };			
		if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); };
		if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); };	
		container.parent().hide();	
		menu.menuOpen = false;
		jQuery(document).unbind('click', killAllMenus);
		jQuery(document).unbind('keydown');
	};
	
	this.showLoading = function(){
		caller.addClass(options.loadingState);
	};

	this.showMenu = function(){
		killAllMenus();
		if (!menu.menuExists) { menu.create() };
		caller
			.addClass('fg-menu-open')
			.addClass(options.callerOnState);
		container.parent().show().click(function(){
		    menu.kill();
		    location.href = caller[0].href;
		    return false;
		});
		container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)');
		menu.menuOpen = true;
		caller.removeClass(options.loadingState);
		jQuery(document).click(killAllMenus);
		
		// assign key events
		jQuery(document).keydown(function(event){
			var e;
			if (event.which !="") { e = event.which; }
			else if (event.charCode != "") { e = event.charCode; }
			else if (event.keyCode != "") { e = event.keyCode; }
			
			var menuType = (jQuery(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ;
			
			switch(e) {
				case 37: // left arrow 
					if (menuType == 'flyout') {
						jQuery(event.target).trigger('mouseout');
						if (jQuery('.'+options.flyOutOnState).size() > 0) { jQuery('.'+options.flyOutOnState).trigger('mouseover'); };
					};
					
					if (menuType == 'ipod') {
						jQuery(event.target).trigger('mouseout');
						if (jQuery('.fg-menu-footer').find('a').size() > 0) { jQuery('.fg-menu-footer').find('a').trigger('click'); };
						if (jQuery('.fg-menu-header').find('a').size() > 0) { jQuery('.fg-menu-current-crumb').prev().find('a').trigger('click'); };
						if (jQuery('.fg-menu-current').prev().is('.fg-menu-indicator')) {
							jQuery('.fg-menu-current').prev().trigger('mouseover');							
						};						
					};
					return false;
					break;
					
				case 38: // up arrow 
					if (jQuery(event.target).is('.' + options.linkHover)) {	
						var prevLink = jQuery(event.target).parent().prev().find('a:eq(0)');						
						if (prevLink.size() > 0) {
							jQuery(event.target).trigger('mouseout');
							prevLink.trigger('mouseover');
						};						
					}
					else { container.find('a:eq(0)').trigger('mouseover'); }
					return false;
					break;
					
				case 39: // right arrow 
					if (jQuery(event.target).is('.fg-menu-indicator')) {						
						if (menuType == 'flyout') {
							jQuery(event.target).next().find('a:eq(0)').trigger('mouseover');
						}
						else if (menuType == 'ipod') {
							jQuery(event.target).trigger('click');						
							setTimeout(function(){
								jQuery(event.target).next().find('a:eq(0)').trigger('mouseover');
							}, options.crossSpeed);
						};				
					}; 
					return false;
					break;
					
				case 40: // down arrow 
					if (jQuery(event.target).is('.' + options.linkHover)) {
						var nextLink = jQuery(event.target).parent().next().find('a:eq(0)');						
						if (nextLink.size() > 0) {							
							jQuery(event.target).trigger('mouseout');
							nextLink.trigger('mouseover');
						};				
					}
					else { container.find('a:eq(0)').trigger('mouseover'); }		
					return false;						
					break;
					
				case 27: // escape
					killAllMenus();
					break;
					
				case 13: // enter
					if (jQuery(event.target).is('.fg-menu-indicator') && menuType == 'ipod') {							
						jQuery(event.target).trigger('click');						
						setTimeout(function(){
							jQuery(event.target).next().find('a:eq(0)').trigger('mouseover');
						}, options.crossSpeed);					
					}; 
					break;
			};
		});
	};
	
	this.create = function(){	
		container.css({ width: options.width }).appendTo('body').find('ul:first').not('.fg-menu-breadcrumb').addClass('fg-menu');
		container.find('ul, li a').addClass('ui-corner-all');
		
		// aria roles & attributes
		container.find('ul').attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id'));
		container.find('li').attr('role', 'menuitem');
		container.find('li:has(ul)').attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false');
		container.find('a').attr('tabindex', '-1');
		
		// when there are multiple levels of hierarchy, create flyout or drilldown menu
		if (container.find('ul').size() > 1) {
			if (options.flyOut) { menu.flyout(container, options); }
			else { menu.drilldown(container, options); }	
		}
		else {
			container.find('a').click(function(){
				menu.chooseItem(this);
				return false;
			});
		};	
		
		if (options.linkHover) {
			var allLinks = container.find('.fg-menu li a');
			allLinks.hover(
				function(){
					var menuitem = jQuery(this);
					jQuery('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id');
					jQuery(this).addClass(options.linkHover).focus().parent().attr('id','active-menuitem');
				},
				function(){
					jQuery(this).removeClass(options.linkHover).blur().parent().removeAttr('id');
				}
			);
		};
		
		if (options.linkHoverSecondary) {
			container.find('.fg-menu li').hover(
				function(){
					jQuery(this).siblings('li').removeClass(options.linkHoverSecondary);
					if (options.flyOutOnState) { jQuery(this).siblings('li').find('a').removeClass(options.flyOutOnState); }
					jQuery(this).addClass(options.linkHoverSecondary);
				},
				function(){ jQuery(this).removeClass(options.linkHoverSecondary); }
			);
		};	
		
		menu.setPosition(container, caller, options);
		menu.menuExists = true;
	};
	
	this.chooseItem = function(item){
		menu.kill();
		// edit this for your own custom function/callback:
		// jQuery('#menuSelection').text(jQuery(item).text());	
		location.href = jQuery(item).attr('href');
	};
};

Menu.prototype.flyout = function(container, options) {
	var menu = this;
	
	this.resetFlyoutMenu = function(){
		var allLists = container.find('ul ul');
		allLists.removeClass('ui-widget-content').hide();	
	};
	
	container.addClass('fg-menu-flyout').find('li:has(ul)').each(function(){
		var linkWidth = container.width();
		var showTimer, hideTimer;
		var allSubLists = jQuery(this).find('ul');		
		
		allSubLists.css({ left: linkWidth, width: linkWidth }).hide();
			
		jQuery(this).find('a:eq(0)').addClass('fg-menu-indicator').html('<span>' + jQuery(this).find('a:eq(0)').text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>').hover(
			function(){
				clearTimeout(hideTimer);
				var subList = jQuery(this).next();
				if (!fitVertical(subList, jQuery(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); };
				if (!fitHorizontal(subList, jQuery(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 999 }); };
				showTimer = setTimeout(function(){
					subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true');	
				}, 300);	
			},
			function(){
				clearTimeout(showTimer);
				var subList = jQuery(this).next();
				hideTimer = setTimeout(function(){
					subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false');
				}, 400);	
			}
		);

		jQuery(this).find('ul a').hover(
			function(){
				clearTimeout(hideTimer);
				if (jQuery(this).parents('ul').prev().is('a.fg-menu-indicator')) {
					jQuery(this).parents('ul').prev().addClass(options.flyOutOnState);
				}
			},
			function(){
				hideTimer = setTimeout(function(){
					allSubLists.hide(options.showSpeed);
					container.find(options.flyOutOnState).removeClass(options.flyOutOnState);
				}, 500);	
			}
		);	
	});
	
	container.find('a').click(function(){
		menu.chooseItem(this);
		return false;
	});
};


Menu.prototype.drilldown = function(container, options) {
	var menu = this;	
	var topList = container.find('.fg-menu');	
	var breadcrumb = jQuery('<ul class="fg-menu-breadcrumb ui-widget-header ui-corner-all ui-helper-clearfix"></ul>');
	var crumbDefaultHeader = jQuery('<li class="fg-menu-breadcrumb-text">'+options.crumbDefaultText+'</li>');
	var firstCrumbText = (options.backLink) ? options.backLinkText : options.topLinkText;
	var firstCrumbClass = (options.backLink) ? 'fg-menu-prev-list' : 'fg-menu-all-lists';
	var firstCrumbLinkClass = (options.backLink) ? 'ui-state-default ui-corner-all' : '';
	var firstCrumbIcon = (options.backLink) ? '<span class="ui-icon ui-icon-triangle-1-w"></span>' : '';
	var firstCrumb = jQuery('<li class="'+firstCrumbClass+'"><a href="#" class="'+firstCrumbLinkClass+'">'+firstCrumbIcon+firstCrumbText+'</a></li>');
	
	container.addClass('fg-menu-ipod');
	
	if (options.backLink) { breadcrumb.addClass('fg-menu-footer').appendTo(container).hide(); }
	else { breadcrumb.addClass('fg-menu-header').prependTo(container); };
	breadcrumb.append(crumbDefaultHeader);
	
	var checkMenuHeight = function(el){
		if (el.height() > options.maxHeight) { el.addClass('fg-menu-scroll') };	
		el.css({ height: options.maxHeight });
	};
	
	var resetChildMenu = function(el){ el.removeClass('fg-menu-scroll').removeClass('fg-menu-current').height('auto'); };
	
	this.resetDrilldownMenu = function(){
		jQuery('.fg-menu-current').removeClass('fg-menu-current');
		topList.animate({ left: 0 }, options.crossSpeed, function(){
			jQuery(this).find('ul').each(function(){
				jQuery(this).hide();
				resetChildMenu(jQuery(this));				
			});
			topList.addClass('fg-menu-current');			
		});		
		jQuery('.fg-menu-all-lists').find('span').remove();	
		breadcrumb.empty().append(crumbDefaultHeader);		
		jQuery('.fg-menu-footer').empty().hide();	
		checkMenuHeight(topList);		
	};
	
	topList
		.addClass('fg-menu-content fg-menu-current ui-widget-content ui-helper-clearfix')
		.css({ width: container.width() })
		.find('ul')
			.css({ width: container.width(), left: container.width() })
			.addClass('ui-widget-content')
			.hide();		
	checkMenuHeight(topList);	
	
	topList.find('a').each(function(){
		// if the link opens a child menu:
		if (jQuery(this).next().is('ul')) {
			jQuery(this)
				.addClass('fg-menu-indicator')
				.each(function(){ jQuery(this).html('<span>' + jQuery(this).text() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>'); })
				.click(function(){ // ----- show the next menu			
					var nextList = jQuery(this).next();
		    		var parentUl = jQuery(this).parents('ul:eq(0)');   		
		    		var parentLeft = (parentUl.is('.fg-menu-content')) ? 0 : parseFloat(topList.css('left'));    		
		    		var nextLeftVal = Math.round(parentLeft - parseFloat(container.width()));
		    		var footer = jQuery('.fg-menu-footer');
		    		
		    		// show next menu   		
		    		resetChildMenu(parentUl);
		    		checkMenuHeight(nextList);
					topList.animate({ left: nextLeftVal }, options.crossSpeed);						
		    		nextList.show().addClass('fg-menu-current').attr('aria-expanded', 'true');    
		    		
		    		var setPrevMenu = function(backlink){
		    			var b = backlink;
		    			var c = jQuery('.fg-menu-current');
			    		var prevList = c.parents('ul:eq(0)');
			    		c.hide().attr('aria-expanded', 'false');
		    			resetChildMenu(c);
		    			checkMenuHeight(prevList);
			    		prevList.addClass('fg-menu-current').attr('aria-expanded', 'true');
			    		if (prevList.hasClass('fg-menu-content')) { b.remove(); footer.hide(); };
		    		};		
		
					// initialize "back" link
					if (options.backLink) {
						if (footer.find('a').size() == 0) {
							footer.show();
							jQuery('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>')
								.appendTo(footer)
								.click(function(){ // ----- show the previous menu
									var b = jQuery(this);
						    		var prevLeftVal = parseFloat(topList.css('left')) + container.width();		    						    		
						    		topList.animate({ left: prevLeftVal },  options.crossSpeed, function(){
						    			setPrevMenu(b);
						    		});			
									return false;
								});
						}
					}
					// or initialize top breadcrumb
		    		else { 
		    			if (breadcrumb.find('li').size() == 1){				
							breadcrumb.empty().append(firstCrumb);
							firstCrumb.find('a').click(function(){
								menu.resetDrilldownMenu();
								return false;
							});
						}
						jQuery('.fg-menu-current-crumb').removeClass('fg-menu-current-crumb');
						var crumbText = jQuery(this).find('span:eq(0)').text();
						var newCrumb = jQuery('<li class="fg-menu-current-crumb"><a href="javascript://" class="fg-menu-crumb">'+crumbText+'</a></li>');	
						newCrumb
							.appendTo(breadcrumb)
							.find('a').click(function(){
								if (jQuery(this).parent().is('.fg-menu-current-crumb')){
									menu.chooseItem(this);
								}
								else {
									var newLeftVal = - (jQuery('.fg-menu-current').parents('ul').size() - 1) * 180;
									topList.animate({ left: newLeftVal }, options.crossSpeed, function(){
										setPrevMenu();
									});
								
									// make this the current crumb, delete all breadcrumbs after this one, and navigate to the relevant menu
									jQuery(this).parent().addClass('fg-menu-current-crumb').find('span').remove();
									jQuery(this).parent().nextAll().remove();									
								};
								return false;
							});
						newCrumb.prev().append(' <span class="ui-icon '+options.nextCrumbLink+'"></span>');
		    		};			
		    		return false;    		
    			});
		}
		// if the link is a leaf node (doesn't open a child menu)
		else {
			jQuery(this).click(function(){
				menu.chooseItem(this);
				return false;
			});
		};
	});
};


/* Menu.prototype.setPosition parameters (defaults noted with *):
	referrer = the link (or other element) used to show the overlaid object 
	settings = can override the defaults:
		- posX/Y: where the top left corner of the object should be positioned in relation to its referrer.
				X: left*, center, right
				Y: top, center, bottom*
		- offsetX/Y: the number of pixels to be offset from the x or y position.  Can be a positive or negative number.
		- directionH/V: where the entire menu should appear in relation to its referrer.
				Horizontal: left*, right
				Vertical: up, down*
		- detectH/V: detect the viewport horizontally / vertically
		- linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */

Menu.prototype.setPosition = function(widget, caller, options) { 
	var el = widget;
	var referrer = caller;
	var dims = {
		refX: referrer.offset().left,
		refY: referrer.offset().top,
		refW: referrer.getTotalWidth(),
		refH: referrer.getTotalHeight()
	};	
	var options = options;
	var xVal, yVal;
	
	var helper = jQuery('<div class="positionHelper"></div>');
	helper.css({ position: 'absolute', left: dims.refX, top: dims.refY, width: dims.refW, height: dims.refH, 'cursor': 'pointer' });
	el.wrap(helper);
	
	// get X pos
	switch(options.positionOpts.posX) {
		case 'left': 	xVal = 0; 
			break;				
		case 'center': xVal = dims.refW / 2;
			break;				
		case 'right': xVal = dims.refW;
			break;
	};
	
	// get Y pos
	switch(options.positionOpts.posY) {
		case 'top': 	yVal = 0;
			break;				
		case 'center': yVal = dims.refH / 2;
			break;				
		case 'bottom': yVal = dims.refH;
			break;
	};
	
	// add the offsets (zero by default)
	xVal += options.positionOpts.offsetX;
	yVal += options.positionOpts.offsetY;
	
	// position the object vertically
	if (options.positionOpts.directionV == 'up') {
		el.css({ top: 'auto', bottom: yVal });
		if (options.positionOpts.detectV && !fitVertical(el)) {
			el.css({ bottom: 'auto', top: yVal });
		}
	} 
	else {
		el.css({ bottom: 'auto', top: yVal });
		if (options.positionOpts.detectV && !fitVertical(el)) {
			el.css({ top: 'auto', bottom: yVal });
		}
	};
	
	// and horizontally
	if (options.positionOpts.directionH == 'left') {
		el.css({ left: 'auto', right: xVal });
		if (options.positionOpts.detectH && !fitHorizontal(el)) {
			el.css({ right: 'auto', left: xVal });
		}
	} 
	else {
		el.css({ right: 'auto', left: xVal });
		if (options.positionOpts.detectH && !fitHorizontal(el)) {
			el.css({ left: 'auto', right: xVal });
		}
	};
	
	// if specified, clone the referring element and position it so that it appears on top of the menu
	if (options.positionOpts.linkToFront) {
		referrer.clone().addClass('linkClone').css({
			position: 'absolute', 
			top: 0, 
			right: 'auto', 
			bottom: 'auto', 
			left: 0, 
			width: referrer.width(), 
			height: referrer.height()
		}).insertAfter(el);
	};
};


/* Utilities to sort and find viewport dimensions */

function sortBigToSmall(a, b) { return b - a; };

jQuery.fn.getTotalWidth = function(){
	return jQuery(this).width() + parseInt(jQuery(this).css('paddingRight')) + parseInt(jQuery(this).css('paddingLeft')) + parseInt(jQuery(this).css('borderRightWidth')) + parseInt(jQuery(this).css('borderLeftWidth'));
};

jQuery.fn.getTotalHeight = function(){
	return jQuery(this).height() + parseInt(jQuery(this).css('paddingTop')) + parseInt(jQuery(this).css('paddingBottom')) + parseInt(jQuery(this).css('borderTopWidth')) + parseInt(jQuery(this).css('borderBottomWidth'));
};

function getScrollTop(){
	return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
};

function getScrollLeft(){
	return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
};

function getWindowHeight(){
	var de = document.documentElement;
	return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
};

function getWindowWidth(){
	var de = document.documentElement;
	return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
};

/* Utilities to test whether an element will fit in the viewport
	Parameters:
	el = element to position, required
	leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */
	
function fitHorizontal(el, leftOffset){
	var leftVal = parseInt(leftOffset) || jQuery(el).offset().left;
	return (leftVal + jQuery(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0);
};

function fitVertical(el, topOffset){
	var topVal = parseInt(topOffset) || jQuery(el).offset().top;
	return (topVal + jQuery(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0);
};

/*-------------------------------------------------------------------- 
 * javascript method: "pxToEm"
 * by:
   Scott Jehl (scott@filamentgroup.com) 
   Maggie Wachs (maggie@filamentgroup.com)
   http://www.filamentgroup.com
 *
 * Copyright (c) 2008 Filament Group
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size.  
 * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/
 * Demo: http://www.filamentgroup.com/examples/pxToEm/	 	
 *							
 * Options:  	 								
 		scope: string or jQuery selector for font-size scoping
 		reverse: Boolean, true reverses the conversion to em-px
 * Dependencies: jQuery library						  
 * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true});
 *
 * Version: 2.0, 08.01.2008 
 * Changelog:
 *		08.02.2007 initial Version 1.0
 *		08.01.2008 - fixed font-size calculation for IE
--------------------------------------------------------------------*/

Number.prototype.pxToEm = String.prototype.pxToEm = function(settings){
	//set defaults
	settings = jQuery.extend({
		scope: 'body',
		reverse: false
	}, settings);
	
	var pxVal = (this == '') ? 0 : parseFloat(this);
	var scopeVal;
	var getWindowWidth = function(){
		var de = document.documentElement;
		return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
	};	
	
	/* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size. 
		For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size. 	
		When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size) 
		to get an accurate em value. */
				
	if (settings.scope == 'body' && jQuery.browser.msie && (parseFloat(jQuery('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) {
		var calcFontSize = function(){		
			return (parseFloat(jQuery('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16;
		};
		scopeVal = calcFontSize();
	}
	else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); };
			
	var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em';
	return result;
};
