


var BrowserIs_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
	      (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );

var toolTipContextElements = [];   
var toolTipPopupControls = [];   
var _datagridConstantDateStoragePattern = "";
var _datagridConstantTimeStoragePattern = "";

var columnHoverviewToolTipControls = [];

// Takes a string and returns the object with the corresponding corresponding
// ID. If an object is passed in, the object is returned. This allows callers
// to accept either the name of an object or the object itself.

function getObject(param) {
	
	if ( typeof(param) == "object" ) {
		
		return param;
		
	} else {
		
		return document.getElementById(param);
		
	}
	
}

// getActiveStyle() takes a DOM object as a parameter and returns that object's
// current, computed style. Just calling object.style provides access to any
// style properties defined using the style="" HTML attribute. It does not
// account for CSS selectors (classes, ids, etc.).

function getActiveStyle(obj) {
	
	// Ensure that we have an object and not just the ID of an HTML element.
	
	obj = getObject(obj);
	
	if ( obj.currentStyle ) {
		
		// Internet Explorer
		
		return obj.currentStyle;
		
	} else if ( document.defaultView && document.defaultView.getComputedStyle ) {
		
		// Mozilla/FireFox
		
		return document.defaultView.getComputedStyle(obj, null);
		
	} else {
		
		// Fall back to non-computed style.
		
		return obj.style;
		
	}
	
}

// Takes n arguments which are the IDs of elements whose style display mode will
// be set to block if not already displayed.

function setDisplay() {
	
	for ( var i = 0; i < arguments.length; i++ ) {
		
		var obj = getObject(arguments[i]);
		
		var objStyle = getActiveStyle(obj);
		
		// Since all elements are hidden with a value of "none", whereas each
		// element may have its own display value, we'll check for "none".
		
		if ( objStyle.display == "none" ){
			
			display(obj);
			
		}
		
	}
	
}

// Takes n arguments which are the IDs of elements whose style display mode will
// be set to non if not already hidden.

function setHide() {
	
	for ( var i = 0; i < arguments.length; i++ ) {
		
		var obj = getObject(arguments[i]);
		
		var objStyle = getActiveStyle(obj);
		
		// Since all elements are hidden with a value of "none", whereas each
		// element may have its own display value, we'll check for "none".
		
		if ( objStyle.display != "none" ){
			
			hide(obj);
			
		}
		
	}
	
}

// Takes n arguments which are the IDs of elements whose style display mode will
// be toggled from none to block.

function toggleDisplay() {
	
	for ( var i = 0; i < arguments.length; i++ ) {
		
		var obj = getObject(arguments[i]);
		
		var objStyle = getActiveStyle(obj);
		
		// Since all elements are hidden with a value of "none", whereas each
		// element may have its own display value, we'll check for "none".
		
		if ( objStyle.display == "none" ){
			
			display(obj);
			
		} else {
			
			hide(obj);
			
		}
		
	}
	
}

function display(obj) {
	
	obj.style.display = getDefaultDisplay(obj);
	
	obj.style.visibility = "visible";
	
}


function hide(obj) {
	
	obj.style.display = "none";

	obj.style.visibility = "hidden";
	
}

// Determines the default display value for the object's HTML element type. For
// instance, a DIV would have a default display of "block". This method should
// ensure that we use the correct display value for each browser.

function getDefaultDisplay(obj) {
	
	var value = "";
	
	// Create a new element with a tag name that corresponds to the object.
	
	var objCopy = document.createElement(obj.tagName);
	
	// Unless we add the element to the document, we won't know the actual
	// display value. IE will return an empty string; Firefox, "block".
	
	// By setting the visibility to hidden, we ensure that the user will not
	// see any such changes.
	
	objCopy.visibility = "hidden";
	
	document.body.appendChild(objCopy);
	
	value = getActiveStyle(objCopy).display;
	
	document.body.removeChild(objCopy);
	
	return value;
	
}

function addSaveEventListener(element, eventName, listener) {
	
	if (element.addEventListener) {
		
		// DOM standard method (Firefox).
		
		element.addEventListener(eventName, listener, true);
		
	} else if (element.attachEvent) {
		
		// Internet Explorer method (pre-dates DOM method).
		
		element.attachEvent("on" + eventName, listener);
		
	} else {
		
		// Old DOM 0 method
		
		element["on" + eventName] = listener;
		
	}
	
}
// Global variables used for pop up client/server communication

//_jsrs_serverScript = null
//_jsrs_callBackFunction = null
//_jsrs_serverFunction = null
//_jsrs_serverFunctionArguments = null
_jsrs_timeout = null;
//_jsrs_htmlObject = null

// global pop-up functions

function clearPopUpTimeout() {
	
	if ( _jsrs_timeout != null ) {
		
		window.clearTimeout(_jsrs_timeout);
		
		_jsrs_timeout = null;
		
	}
	
}

// Select list pop up functions

function OnClickCallback(URL, Control)
{
	YAHOO.util.Connect.asyncRequest('GET', URL, CreateCallback(Control));
}

function CreateCallback(Control)
{
		var callback =
		{
			success:ReceiveServerData,
			failure:ProcessCallBackError,
			argument: { control:Control }
		};
		return callback;
}

function ReceiveServerData(o)
{
	_jsrs_timeout = null;
	if (o.responseText !== undefined)
	{
		if (o.argument.control !== undefined)
		{
			o.argument.control.TableCell.PopupText = "stop";
			
			o.argument.control.cfg.setProperty ( "text", o.responseText, false );
		}
	}
}

function ProcessCallBackError(arg, context)
{
	_jsrs_timeout = null;
	if(o.responseText !== undefined)
	{
		if (o.argument.control !== undefined)
		{
			o.argument.control.title = o.statusText;
    }
	}
}

function popUpSelectListInfo(queryString, tableCell)
{
	if ( !tableCell.PopupText )
	{
		var Index = toolTipPopupControls.length;
		toolTipPopupControls[Index] = new YAHOO.widget.Tooltip("toolTipPopupControls[" + Index + "]", { context:tableCell.id,autodismissdelay:60000,text:"Loading...",effect:{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.15} } );
		
		toolTipPopupControls[Index].TableCell = tableCell;
		
		var func = function(){OnClickCallback(queryString, toolTipPopupControls[Index])}
		_jsrs_timeout = window.setTimeout(func, 500); 
	}	
}

function popUpSelectListInfoOut() {
	
	clearPopUpTimeout();
	
}

/** Dynamic List stuff **/

var kSELECTLIST_URL_ATTR       = "cb:selecturl";     // url for ajax call
var kSELECTLIST_WORKING_ATTR   = "cb:working";       // to keep track of whether current drop-down task is done (esp. necessary for Firefox)
var kSELECTLIST_INBOX_ATTR     = "cb:inbox";         // to keep track of whether focus is in box
var kSELECTLIST_LOADED_ATTR    = "cb:loaded";        // whether we've ever been loaded
var kSELECTLIST_FORCE_INITIAL  = "cb:forceLoad";     // whether to automatically trigger an initial load
var kSELECTLIST_NEEDED_ATTR    = "cb:neededParams";  // comma-separated list of fields (field ids) needed along with request
var kSELECTLIST_DEPENDENTS_ATTR = "cb:dependents";   // comma-separated list of list fields (field ids) that depend on this field
var kSELECTLIST_IS_ROW_SPECIFIC  = "cb:rowSpecific"; // Can results be copied to other rows?
var kSELECTLIST_FORCE_VALID_ATTR = "cb:forceValid";  // whether to suppress invalid values (used during Add, or if parent field changes during Edit)
var kSELECTLIST_OLD_VALUE_ATTR = "cb:oldValue";      // old, invalidated value that may become valid again if parent field changes
var kSELECTLIST_NEEDSROW_ATTR  = "cb:needsRow";      // whether we're really dependent on row fields (as opposed to just page params)
var kSELECTLIST_ID_PREFIX_ATTR = "cb:idPrefix";
var kSELECTLIST_ID_ROWNUM_ATTR = "cb:idRowNum";
var kExtraPrefixes             = [ "Drill.", "Shared." ];
var kHiddenFilterPrefix        = "Filter.Hide.";
var kAuthFailedMessage         = "Not authenticated. Your session may have timed out.";


function setupLazyLoad(element)
{
	var selectListURL = element.getAttribute(kSELECTLIST_URL_ATTR);

	if (selectListURL == null)
        return; // short-circuit

	element.onfocus     = loadSelectList;
	element.onmousedown = trackingSelectList;
	element.onmouseup   = resetSelectList;
	element.onblur      = resetSelectList;
	element.onmouseover = loadSelectList;
	element.onmouseout  = resetSelectList;
    
    setupDependencies(element);
    
    var forceInitialLoad = element.getAttribute(kSELECTLIST_FORCE_INITIAL);
	
	if (forceInitialLoad != null)
	    refreshSelectBox(element);
}


function resetWidths(sourceBox, newWidth)
{
    var maxBoxes = 30;
    var idPrefix     = sourceBox.getAttribute(kSELECTLIST_ID_PREFIX_ATTR);
    var idRowNum     = sourceBox.getAttribute(kSELECTLIST_ID_ROWNUM_ATTR);
    
    if (idRowNum == null)
        return; // short-circuit; we don't have multiple rows
    
    var boxPrefix = idPrefix + idRowNum + ".";
    var idSuffix = sourceBox.id.substring(boxPrefix.length);
    
    for (var i = 1; i <= maxBoxes; i++)
    {
        var id = idPrefix + i + "." + idSuffix;
        
        if (id == sourceBox.id) continue; // skip calling box
        
        var box = document.getElementById(id);
        
        if (box == null) break; // no more left
        
        box.style.width = newWidth + 'px';
    }
}

function receiveSelectBoxData(o)
{
    var box = o.argument.selectBox;

    if ((o.responseText !== undefined) && (o.responseText != null) && (o.responseText.length > 0))
    {
        var response = eval(o.responseText);
        
        if (!response.authOK)
        {
            alert(kAuthFailedMessage);
            return;
        }
                
        repopulateSelectBox(box, response);
        
        box.setAttribute(kSELECTLIST_LOADED_ATTR,"true");
        
        if (!isReallyDependent(box))
            updateWholeColumn(box, response);
    }

    box.disabled = false;

    jsLog('done loading: ' + box.id);
    if (_jsLoggingOn)
        jsLog('sql for ' + box.id + ': ' + unescape(box.getAttribute(kSELECTLIST_URL_ATTR).replace(/\+/g,' ')));

    var wantFocus = ("true" == box.getAttribute(kSELECTLIST_INBOX_ATTR));

    if (wantFocus)
    {
        box.focus();
    }
}

function refreshSelectBox(box, value, allowInsert)
{
jsLog('refreshing: ' + box.id + ' with: ' + value + ' (allowInsert=' + allowInsert + ')');
    if (value != null)
    {
        // clear the box. preserve the 0'th empty (translated choose/none) option, if possible
        // (it should always be there, but let's not assume)
        box.options.length = (box.options.length > 0) && (box.options[0].value.length == 0) ? 1 : 0;

        box.options[box.options.length] = new Option(value, value);
        box.selectedIndex = box.options.length - 1;
    }
    // else we're just forcing a refresh
    
    box.setAttribute(kSELECTLIST_FORCE_VALID_ATTR, (allowInsert ? "false" : "true"));
    box.setAttribute(kSELECTLIST_LOADED_ATTR, "false");
    
    var fakeEvent = new Object({ target : box, type : "internal" });

    loadSelectList (fakeEvent);
    resetSelectList(fakeEvent);
}

function updateWholeColumn(box, response)
{
    var idRowNum = box.getAttribute(kSELECTLIST_ID_ROWNUM_ATTR);
    
    if (idRowNum == null)
        return; // short-circuit; we're not in full-page mode

    var idPrefix = box.getAttribute(kSELECTLIST_ID_PREFIX_ATTR);
    var wholePrefixLength = idPrefix.length + idRowNum.length + ".".length;
    var idLeaf   = box.id.substring(wholePrefixLength);
    
    idRowNum = parseInt(idRowNum);
    
    // TBD: do i know the range of edit rows?
    // Assuming not, go down and up from the current row 'til no element is found  
    for (var i = (idRowNum - 1); i >= 0; i--)
    {
        var id         = idPrefix + i + "." + idLeaf;
        var siblingBox = document.getElementById(id);
        
        if (siblingBox == null) break; // we're done
        
        repopulateSelectBox(siblingBox, response);
        
        siblingBox.setAttribute(kSELECTLIST_LOADED_ATTR,"true");
    }
    
    for (var i = (idRowNum + 1); i < 999; i++)
    {
        var id         = idPrefix + i + "." + idLeaf;
        var siblingBox = document.getElementById(id);
        
        if (siblingBox == null) break; // we're done
        
        repopulateSelectBox(siblingBox, response);
        
        siblingBox.setAttribute(kSELECTLIST_LOADED_ATTR,"true");
    }
}

function emptySelectBox(box)
{
    var dummyResponse = { error: "", overLimit:false, listValues: [] };
    
    repopulateSelectBox(box, dummyResponse);
}

function repopulateSelectBox(box, response)
{
    var msg = null;        
        
    if (response.error.length > 0)
    {
        msg = "error for list [" + box.id + "]: " + response.error;
    }
    else if (response.overLimit)
    {
        msg = "warning for list [" + box.id + "]: Couldn't retrieve all values.";
    }

    if (msg != null)
    {
        jsLog(msg);
        box.title = msg;
        box.style.backgroundColor = 'orange';
    }

    var currOption = box.options[box.selectedIndex];

    if (currOption.value.length == 0)
    {
        var oldValue = box.getAttribute(kSELECTLIST_OLD_VALUE_ATTR);

        if (oldValue != null)
           currOption = new Option('', oldValue); // copy it for use independently of box
    }

    var startWidth = box.offsetWidth;

    box.style.width = null;
    
    // clear the box. preserve the 0'th empty (translated choose/none) option, if possible
    // (it should always be there, but let's not assume)
    box.options.length = (box.options.length > 0) && (box.options[0].value.length == 0) ? 1 : 0;
    box.selectedIndex = 0;
    
    for (var i = 0; i < response.listValues.length; i++)
    {
        var value = response.listValues[i];
        var text  = response.listText  [i];

        if (text.length == 0)
            text = value;

        var newIndex = box.options.length;
        
        box.options[newIndex] = new Option(text, value);

        if (value == currOption.value)
        {
            box.selectedIndex = newIndex;
        }
    }

    // make sure existing value still available // TBD: always?!
    if (box.options[box.selectedIndex].value != currOption.value)
    {
        var forceValid = ("true" == box.getAttribute(kSELECTLIST_FORCE_VALID_ATTR));

        if (forceValid) // save off currOption in case it becomes valid again
        {
            box.setAttribute(kSELECTLIST_OLD_VALUE_ATTR, currOption.value);
        }
        else
        {
            box.options[box.options.length] = new Option("---", "");
            box.options[box.options.length] = new Option(currOption.text, currOption.value);
            box.selectedIndex = box.options.length - 1;
        }
    }
    
    var doneWidth = box.offsetWidth;
    
    if (doneWidth >= startWidth)
    {
        resetWidths(box, doneWidth);
    }
    else if (doneWidth < startWidth)
    {
        box.style.width = startWidth + 'px';
    }
}

function selectListWantsRefresh(whichSelectBox)
{
    var wantRefresh = false;
    var alreadyWorking = ("true" == whichSelectBox.getAttribute(kSELECTLIST_WORKING_ATTR));
    var stillInBox     = ("true" == whichSelectBox.getAttribute(kSELECTLIST_INBOX_ATTR));
    var everLoaded     = ("true" == whichSelectBox.getAttribute(kSELECTLIST_LOADED_ATTR));
//    var isDependent    = isReallyDependent(whichSelectBox);
    var isDependent    = false;
                            
    // TODO: can we be smarter and also check whether form data has actually changed?

    wantRefresh = (isDependent || !everLoaded) && !alreadyWorking && !stillInBox;

    return wantRefresh;
}

function isReallyDependent(whichSelectBox)
{
    var needsSubstitution = (whichSelectBox.getAttribute(kSELECTLIST_NEEDED_ATTR).length > 0);
    var needsDataFromRow = ("false" != whichSelectBox.getAttribute(kSELECTLIST_NEEDSROW_ATTR)); // false must be set explicitly
    
    return needsSubstitution && 
           needsDataFromRow || 
           whichSelectBox.getAttribute(kSELECTLIST_IS_ROW_SPECIFIC) == "True";
}

function doFilter(url, element)
{
    var filterWhereClause = prepWhereClause(element, kHiddenFilterPrefix);

    if (filterWhereClause != null) // prep must succeed or no popup
    {
        url += filterWhereClause;

        popupWindowNoMenu(url, 500, 800);
    }
    else 
    {
        alert("Missing required fields for combo-box ListWhereClause.");
    }
}

function doInsertToList(url, element, isMini)
{
    if (isMini)
        popupWindowNoMenu(url, 175, 400);
    else
        popupWindowNoMenu(url, 500, 800);
}

function setupDependencies(element)
{
    var dependsOnRowData = false;
    var neededParams = element.getAttribute(kSELECTLIST_NEEDED_ATTR).split(",");
    var idPrefix     = element.getAttribute(kSELECTLIST_ID_PREFIX_ATTR);
    var idRowNum     = element.getAttribute(kSELECTLIST_ID_ROWNUM_ATTR);

    idRowNum = (idRowNum != null) ? (idRowNum + ".") : "";
    
    for (var i = 0; i < neededParams.length; i++)
    {
        var id = neededParams[i];

        if (id.length == 0)
            continue;

        var fieldId = idPrefix + idRowNum + id;
        var field = document.getElementById(fieldId);
        var warning = null;

        if (field != null)
        {
            dependsOnRowData = true;

            var dependents = field.getAttribute(kSELECTLIST_DEPENDENTS_ATTR);
            
            if (dependents != null)
                dependents += "," + element.id;
            else
                dependents = element.id;
            
            field.setAttribute(kSELECTLIST_DEPENDENTS_ATTR, dependents);
            field.onchange = dependentListProviderChanged;
        }
        else
          ;  // something may be wrong; this will get logged later when element loading is attempted
    }
    
    element.setAttribute(kSELECTLIST_NEEDSROW_ATTR,(dependsOnRowData ? "true" : "false"));
}


function prepWhereClause(element, prefix)
{
    if (prefix == null) prefix = "";
    
    var whereClause  = "";
    var dependsOnRowData = false;
    var neededRowDataIsPresent = true;
    var neededParams = element.getAttribute(kSELECTLIST_NEEDED_ATTR).split(",");
    var idPrefix     = element.getAttribute(kSELECTLIST_ID_PREFIX_ATTR);
    var idRowNum     = element.getAttribute(kSELECTLIST_ID_ROWNUM_ATTR);

    idRowNum = (idRowNum != null) ? (idRowNum + ".") : "";
    
    for (var i = 0; i < neededParams.length; i++)
    {
        var id = neededParams[i];

        if (id.length == 0)
            continue;

        var fieldId = idPrefix + idRowNum + id;
        var field = document.getElementById(fieldId);
        var warning = null;

        if (field != null)
        {
            dependsOnRowData = true;
        }
        else
        {
            for (var j = 0; j < kExtraPrefixes.length ; j++)
            {
                var extraFieldId = kExtraPrefixes[j] + id;   
                field = document.getElementById(extraFieldId);

                if (field != null)
                    break;
            }
        }
        
        if (field != null)
        {
            if (field.value.length == 0)
            {
                jsLog("Warning: missing data for: [" + fieldId + "]");
                neededRowDataIsPresent = false;
            }

            whereClause += "&" + prefix + id + "=" + field.value;
        }
        else
        {
            jsLog("Warning: missing dynamic param: [" + fieldId + "]");
            // Something MAY be wrong, but not our job to deal with it here.
            // A known case is where there are successfully #-substituted table names in the where clause
            // that can't and should not be re-resolved
        }
    }
    
    element.setAttribute(kSELECTLIST_NEEDSROW_ATTR,(dependsOnRowData ? "true" : "false"));
    
    if (!neededRowDataIsPresent)
        whereClause = null;
        
    return whereClause;
}

function loadSelectList(evt)
{
    evt = (evt) ? evt : window.event;
    
    var box = (evt.srcElement) ? evt.srcElement : evt.target;

    if (box.id.length == 0) return; // Firefox sends us here during list tracking; ignore

	if (!selectListWantsRefresh(box))
	{
	    box.disabled = false; // in case box has been refreshed behind its back (e.g. UpdateWholeColumn)
	    return; // short-circuit
    }

    var whereClause = prepWhereClause(box);

    if (whereClause == null)
    {
        emptySelectBox(box);
        return; // prep failed. TODO: add tooltip?
    }
    
    var wantFocus = (evt.type == "focus");

    box.setAttribute(kSELECTLIST_WORKING_ATTR, "true");
    box.setAttribute(kSELECTLIST_INBOX_ATTR  , (wantFocus ? "true" : "false"));

    box.disabled = true;
    
    var url = box.getAttribute(kSELECTLIST_URL_ATTR) + whereClause;
    var callback = {
        success : receiveSelectBoxData,
        failure : ProcessCallBackError,
        argument: { selectBox : box }
    };

    YAHOO.util.Connect.asyncRequest('GET', url, callback);
}

function resetSelectList(evt)
{
    evt = (evt) ? evt : window.event;
    
    var box = (evt.srcElement) ? evt.srcElement : evt.target;
    var doneTracking = (evt.type == "blur") || (evt.type == "mouseup");
    
    box.setAttribute(kSELECTLIST_WORKING_ATTR, "false");

    if (doneTracking)
        trackingSelectList(evt);
}

function dependentListProviderChanged(evt)
{
    evt = (evt) ? evt : window.event;
    
    var box = (evt.srcElement) ? evt.srcElement : evt.target;
    
    var dependents = box.getAttribute(kSELECTLIST_DEPENDENTS_ATTR);

    if (dependents == null)
        return;
        
    dependents = dependents.split(",");
    
    for (var i = 0; i < dependents.length; i++)
    {
        var dependent = document.getElementById(dependents[i]);
        
        dependent.setAttribute(kSELECTLIST_FORCE_VALID_ATTR,"true");

	    refreshSelectBox(dependent, dependent.value, false);
    }    
}

function trackingSelectList(evt)
{
    evt = (evt) ? evt : window.event;
    
    var box    = (evt.srcElement) ? evt.srcElement : evt.target;
    var inside = (evt.type == "mousedown");
    
    box.setAttribute(kSELECTLIST_INBOX_ATTR, inside ? "true" : "false");
}

/* Auto-complete stuff */

var kAC_PAGEID_ATTR       = "SQLPageID";
var kAC_TARGET_ATTR       = "acTarget";
var kAC_SQL_ATTR          = "acSQL";
var kAC_SEARCH_CHARS_ATTR = "acSearchChars";
var kAC_NEWVAL_SQL_ATTR   = "acNewValSQL";
var kAC_NEWVAL_ATTR       = "acNewValue";
var kATTR_PREFIX          = "cb:";
var kAC_ID_PREFIX         = "ac_";
var kAC_LAZYLOAD_DATASOURCEID = "ListDataSourceID";

function prepareAC(box, index)
{
    var idRowNum = box.getAttribute(kSELECTLIST_ID_ROWNUM_ATTR);

    var container = document.getElementById(box.id + "_div");

    if (idRowNum != null) // in full-page edit we need to give successive rows' AC containers descending z positions (IE)
    {
        container.style.zIndex = 9050 - idRowNum;
    }
    else // Need it in vertical as well
    {
        container.style.zIndex = 9050 - index;
    }

//	box.onfocus = _prepareAC;
//}

//function _prepareAC(evt)
//{
//    evt = (evt) ? evt : window.event;
//    var box    = (evt.srcElement) ? evt.srcElement : evt.target;
   
    var datasource = new YAHOO.util.XHRDataSource("AutoComplete.aspx");

    datasource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON; 
    datasource.responseSchema = { 
            resultsList : "response.items", 
            fields      : ["text", "id"],
            metaFields  : { authOK : "response.authOK" , error : "response.error" }
        }; 

    
    var oAC = new YAHOO.widget.AutoComplete(box.id, box.id + "_list", datasource); 
    
    oAC.queryDelay     = .1;    // Throttle requests sent
    oAC.resultTypeList = false; // turn off backward-compatible AC feature to enable field accessors
    
    oAC.generateRequest = function(searchChars) {
            var box         = this.getInputEl();
            var pageID      = box.getAttribute(kATTR_PREFIX + kAC_PAGEID_ATTR);
            var sql         = box.getAttribute(kATTR_PREFIX + kAC_SQL_ATTR);
            var dsID        = box.getAttribute(kATTR_PREFIX + kAC_LAZYLOAD_DATASOURCEID);
            var dynamicVals = prepWhereClause(box);

            if (dynamicVals == null)
                return "?ac_ignore=true"; // prep failed. TODO: this still does the AJAX call, which will dutifully fail; better to abort altogether, but how?
                
            var params = 
                "?" + kAC_PAGEID_ATTR       + "=" + pageID +
                "&" + kAC_SQL_ATTR          + "=" + sql    + dynamicVals + 
                "&" + kAC_SEARCH_CHARS_ATTR + "=" + searchChars +
                "&" + kAC_LAZYLOAD_DATASOURCEID + "=" + dsID;
            
            return params; 
        };

    oAC.doBeforeLoadData   = function(sQuery , oResponse , oPayload) {
            if (oResponse.meta.error != null)
            {
                var box = this.getInputEl();
                var msg = "error for combo box [" + box.id + "]: " + oResponse.meta.error;

                jsLog(msg);
                box.title = msg;
                box.style.backgroundColor = 'orange';
            }
            else if ((oResponse.meta.authOK !== undefined) && !oResponse.meta.authOK)
                alert(kAuthFailedMessage);
            
            return true; 
        };
    
    var targetID = box.getAttribute(kATTR_PREFIX + kAC_TARGET_ATTR);
    var target   = document.getElementById(targetID);
    var targHandler = function(type, args) {
            var oAC          = args[0];
            var selectedLI   = args[1];
            var selectedData = args[2];
            
            target.value = selectedData.id;

		if ( target.onchange != null )
		{
			var fakeEvent = new Object({ target : target, type : "internal" });
			target.onchange(fakeEvent);
		}
};        
    oAC.itemSelectEvent.subscribe(targHandler);

    var errHandler = function(self, query) {
            jsLog('error retrieving AutoComplete data'); // TODO: do we have any error info??
        };      
    oAC.dataErrorEvent.subscribe(errHandler);
    

    var changeHandler = function(self) {
            if (box.value.length == 0)
                target.value = ""; // they've actually cleared the field
        };      
    oAC.textboxChangeEvent.subscribe(changeHandler);

//    setupDependencies(element); TODO: not ready for this yet!

    var forceInitialLoad = box.getAttribute(kSELECTLIST_FORCE_INITIAL);
    	
	if (forceInitialLoad != null)
	    refreshJumboBox(target, target.value);
}

function presetACBox(targetField, value, desc)
{
    var descID  = kAC_ID_PREFIX + targetField.id;
    var descBox = document.getElementById(descID);
    
    targetField.value = value;
    descBox.value     = (desc != null) ? desc : value;

		if ( targetField.onchange != null )
		{
			var fakeEvent = new Object({ target : targetField, type : "internal" });
			targetField.onchange(fakeEvent);
		}
}

function refreshJumboBox(targetField, value)
{
    var boxID  = kAC_ID_PREFIX + targetField.id;
    var box    = document.getElementById(boxID);
    var pageID = box.getAttribute(kATTR_PREFIX + kAC_PAGEID_ATTR);
    var sql    = box.getAttribute(kATTR_PREFIX + kAC_NEWVAL_SQL_ATTR);
    var dynamicVals = prepWhereClause(box);
    
    if (dynamicVals == null)
        return; // abort if prep failed

    var url = "AutoComplete.aspx" +
        "?" + kAC_PAGEID_ATTR     + "=" + pageID +
        "&" + kAC_NEWVAL_SQL_ATTR + "=" + sql    + dynamicVals + 
        "&" + kAC_NEWVAL_ATTR     + "=" + value;

    var callback = {
        success : receiveResolveJumboBoxData,
        failure : ProcessCallBackError,
        argument: { targetField : targetField }
    };

    YAHOO.util.Connect.asyncRequest('GET', url, callback);
}

function receiveResolveJumboBoxData(o)
{
    var box = o.argument.targetField;

    if ((o.responseText !== undefined) && (o.responseText != null) && (o.responseText.length > 0))
    {
        var response = eval(o.responseText);

        if (!response.authOK)
        {
            alert(kAuthFailedMessage);
            return;
        }
        
        if (response.error.length > 0)
            jsLog("error for jumboBox [" + box.id + "]: " + response.error);

        presetACBox(box, response.value, response.text);
    }
}

/* Logging */
var gLogLine = 0;
var gLog, gLogDiv;

function jsLog(msg)
{
    if (gLogLine < 0)
        return; // logging really disabled
        
    if (gLogLine == 0)
    {
        gLog    = document.getElementById('jsLog');
        gLogDiv = document.getElementById('jsDebug');
    
        if ((gLog == null) || (gLogDiv == null))
        {
            gLogLine = -1; // not found, don't bother with any more logging
            return;
        }
    }

    if (_jsLoggingOn)
        gLogDiv.style.display = "block";       // code wants us to turn on
    else if (gLogDiv.style.display == "block") // local developer manually turned us on
        _jsLoggingOn = true;
    else
        return;

    gLog.innerHTML = '<b>' + ++gLogLine + ':</b> ' + msg + '<br>' + gLog.innerHTML;
}

function toggleVis(elemID)
{
    var elem = document.getElementById(elemID);
    
    if (elem != null)
    {
        elem.style.display = (elem.style.display == "none") ? "block" : "none";
    }
}

/* Page initialization function called onLoad. */

function init()
{
	/* check to see if there is a row to highlight and invoke the onclick event
	 * if so. This will trigger the highlight routine. */

	var element = document.getElementById("DataGridHighlightedRow");
	 
	if ( element != null && element.onclick )
		element.onclick();
	
	autoloadQForms();
	autoloadOnLoadEvents();	
	autoloadToolTips();
	
	YAHOO.util.Event.onContentReady("cranSoftBody", writeUserSessionMessages);
	
	checkLabels();
	
	PageMethods.init();
	
	
	YAHOO.util.Event.on ('TitleHoverViewArea', 'mouseover', function(evt){
	    TitleHoverView.positionXY = YAHOO.util.Event.getXY(evt);
	});
	
	YAHOO.util.Event.on ('TitleHoverViewArea', 'mouseout', function(evt){
	    TitleHoverView.mouseOutFired = true;
	});
	
}

function loadCransoftMenus() {
    onVerticalMenuReady();
    onHorizontalMenuReady();
}

function elementHasKey(element){
	if( element.getAttribute("cb_key") != null )
	{
		return true;
	}

	return false;
}




function elementUsesToolTips(element){
	if( element.getAttribute("cb_toolTip") != null )
	{
		if( element.getAttribute("cb_toolTip") == "true" )
		{
			return true;
		}
	}
	
	return false;
}

function autoloadToolTips() {

	var myArrayOfElements = YAHOO.util.Dom.getElementsBy( elementUsesToolTips, null, null );
	
	for ( var elementIndex = 0; elementIndex < myArrayOfElements.length; elementIndex++ ) {
		toolTipContextElements[toolTipContextElements.length] = myArrayOfElements[elementIndex].id;  
	}
	
	var cbToolTips = new YAHOO.widget.Tooltip("cbToolTips", { context:toolTipContextElements,autodismissdelay:60000,effect:{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.15} } );
}

function autoloadQForms() {
	// fix this up for use by DateTimePattern utilities, which require minutes to be represented by 'n'
	_datagridConstantTimeStoragePattern = _datagridConstantTimeStoragePattern.replace(/m/g,'n');
	
	for ( var formIndex = 0; formIndex < document.forms.length; formIndex++ ) {
		
		var form = document.forms[formIndex];
		
		if ( form.name != "" ) {
		
			eval("objForm_" + formIndex + " = new qForm('" + form.name + "');");
			
			for ( var elementIndex = 0; elementIndex < form.elements.length; elementIndex++ ) {
				
				var element = form.elements[elementIndex];
				
				var description = element.getAttribute("cb:description");
				
				if ( description != null ) {
				
					eval("objForm_" + formIndex + "['" + element.name + "'].description = '" + description.replace(/'/g,'\\\'') + "';");
				}
				
				var required = element.getAttribute("cb:required");
				
				if ( isTrue(required) ) {
					
					eval("objForm_" + formIndex + "['" + element.name + "'].required = true;");
					
					eval("objForm_" + formIndex + "['" + element.name + "'].validateNotNull();");
					
					var allowspace = element.getAttribute("cb:allowspace");
					
					if ( allowspace != "true" ) {

						eval("objForm_" + formIndex + "['" + element.name + "'].validateNotEmpty();");
						
					}
					
				}
				
				var validate = element.getAttribute("cb:validate");
				
				if (validate != null)
				{
					var validateFunction = "objForm_" + formIndex + "['" + element.name + "']";
				    var validationPattern = element.getAttribute("cb:validatepattern");
                    
					switch (validate)
					{
						case "email":
							validateFunction += ".validateEmail();";
							break;
							
						case "date":
							validateFunction += ".validateCbDate('" + validationPattern + "', '" + _datagridConstantDateStoragePattern  + "');";
							break;

						case "datetime":
							validateFunction += ".validateCbDateTime('" + validationPattern + "');";
							break;

						case "time":
							validateFunction += ".validateCbTime('" + validationPattern + "', '" + _datagridConstantTimeStoragePattern  + "');";
							break;
							
						case "numeric":
						case "numericnonnegative":
						case "currency":
						{
						    var patternArgs = validationPattern.split("|");
						    var thousandsDivider   = patternArgs[0];
						    var decimalDivider     = patternArgs[1];
						    var currencyIdentifier = patternArgs[2];
						    var minValue = null;
						    var maxValue = null;
						    var allowNegative = true;
						    
						    if (validate == "numeric")
						    {
							    minimumValue = element.getAttribute("cb:minimumvalue");
							    maximumValue = element.getAttribute("cb:maximumvalue");
						    }
						    else if (validate == "numericnonnegative")
						        allowNegative = false;
							
							validateFunction += ".validateCbNumeric('" + thousandsDivider + 
							            "', '" + decimalDivider + "', '" + currencyIdentifier +
							            "', " + allowNegative + ", " + minValue + ", " + maxValue + ");";
						    
						}
						break;
					}

					eval(validateFunction);
				}
				
			}
		
		}
		
	}
	
}

function myCellIndex(objElement) {

	if (objElement.tagName == 'BODY') {
	
		return null;
		
	} else if (objElement.tagName == 'TD' || objElement.tagName == 'TH' ) {
	
		return objElement.cellIndex;
		
	} else {
		
		return myCellIndex(objElement.parentNode)
	}
}

function myCellColspan(objElement) {

	if (objElement.tagName == 'BODY') {
	
		return 1;
		
	} else if (objElement.tagName == 'TD' || objElement.tagName == 'TH' ) {
	
		return objElement.getAttribute("colspan") ? objElement.getAttribute("colspan") : 1;
		
	} else {
		
		return myCellColspan(objElement.parentNode)
	}
}

function expandCollapsedLabels(forms) {
    var oTbodyArray = new Array();
	
	for ( var iForm = 0; iForm < forms.length; iForm++ ) {
		
		form = forms[iForm];
		
		elements = form.elements;
		
		for ( var iElement = 0; iElement < elements.length; iElement++ ) {
			
			element = elements[iElement];
		    
		    // if this element has no width, ensure it's not because of a collapsed label
			
		    if ( element.offsetWidth == 0 ) {

		        var oParent = element.parentNode;

		        while( oParent != null ) {
				
		            if ( oParent.nodeName == "TBODY" && oParent.style.display == "none" ) {

		                display( oParent );
				
		                oTbodyArray.push( oParent );
					
		                break;
	
		            }

		            oParent = oParent.parentNode;

		        }

		    }

		}

	}

	return oTbodyArray;	
}

function autoloadOnLoadEvents()
{
	var oTbodyArray = expandCollapsedLabels(document.forms);

	var aryColumnWidths = new Array(3);
	aryColumnWidths[0] = null;        // not used 
	aryColumnWidths[1] = new Array(); // cells with colspan 1
	aryColumnWidths[2] = new Array(); // cells with colspan 2

	for (var i = 0; i < document.forms.length; i++)
	{
		var elements = document.forms[i].elements;
		
		for (var j = 0; j < elements.length; j++)
		{
			var element = elements[j];

            handleResize(element, aryColumnWidths);
            setupLazyLoad(element);
            		
			var focusAttribute = element.getAttribute("cb:focus");

			if (isTrue(focusAttribute))
			{
				selectFormField(i, j);
			}
			
			var autoCompleteTarget = element.getAttribute("cb:acTarget");
			
			if (autoCompleteTarget != null)
			{
			    prepareAC(element, j);
			}
		}
	}

	// re-hide any TBODY we had to show
	for (var i = 0; i < oTbodyArray.length; i++)
	{
        hide( oTbodyArray[i] );
    }
}

function handleResize(element, aryColumnWidths)
{
	var resizeAttribute = element.getAttribute("cb:resize");

	if (!isTrue(resizeAttribute))
        return; // short-circuit

	var bufferWidth       = 4;
	var maxWidthAttribute = element.getAttribute("cb:maxwidth");
	var cellIndex         = myCellIndex(element);
	var cellColspan       = myCellColspan(element);
	var elementParent     = element.parentNode;
	var widthToSpare;

	if (aryColumnWidths[cellColspan][cellIndex])
	{
	    widthToSpare = aryColumnWidths[cellColspan][cellIndex];
	} 
	else
	{
		// In Mozilla form elements have a client width of 0, so
		// we'll use the parent to that instead.
		
//		if (elementParent.clientWidth == 0) {

//			widthToSpare = parseInt(elementParent.parentNode.clientWidth,10);

//		} else {
//			
//			widthToSpare = parseInt(elementParent.clientWidth,10) - bufferWidth;

//		}
		if (elementParent.clientWidth > 0)
		{
			widthToSpare = parseInt(elementParent.clientWidth,10) - bufferWidth;
		}
		else if ( elementParent.parentNode.clientWidth > 0 )
		{
			widthToSpare = parseInt(elementParent.parentNode.clientWidth,10);
		}
		else if ( elementParent.parentNode.parentNode.clientWidth > 0 )
		{
			widthToSpare = parseInt(elementParent.parentNode.parentNode.clientWidth,10);
		}
		else if ( elementParent.parentNode.parentNode.parentNode.clientWidth > 0 )
		{
			widthToSpare = parseInt(elementParent.parentNode.parentNode.parentNode.clientWidth,10);
		}
		else if ( elementParent.parentNode.parentNode.parentNode.clientWidth > 0 )
		{
			widthToSpare = parseInt(elementParent.parentNode.parentNode.parentNode.clientWidth,10);
		}					
		
		if (element.nodeName == 'TEXTAREA')
		{ 
			// IE workaround
			// If a textarea has a style width of 100% IE will ignore the cols attribute
			// This fix will calculate what the width would have been if cols were observed,
			// and select the largest of the two values.
			var colWidth = parseInt(element.getAttribute("cols"), 10) * 7 + 36;
			
			widthToSpare = Math.max(widthToSpare, colWidth);
		}				

		aryColumnWidths[cellColspan][cellIndex] = widthToSpare;
	}
	
	for (var i = 0; i < elementParent.childNodes.length; i++)
	{
		if (elementParent.childNodes[i].nodeType == 1)
		{
			widthToSpare -= parseInt(elementParent.childNodes[i].clientWidth, 10);
		}
	}
	
	if (!isNaN(widthToSpare) && widthToSpare > 0)
	{
		var newWidth = element.clientWidth + widthToSpare;

		if ( maxWidthAttribute != null && !isNaN(maxWidthAttribute) )
		{
			if ( newWidth > maxWidthAttribute )
			{
				newWidth = maxWidthAttribute;
			}
		}
       
        // RLR this is a hack to correct the lineup of controls on the login page
       if (BrowserIs_ie && (element.nodeName == "INPUT"))
            newWidth = newWidth - 6;
        
		element.style.width = newWidth + 'px';
	}
}

function selectFormField(formIndex, fieldIndex)
{
	
	// First, make sure the proper window/frame has focus. Otherwise, the tab
	// sequence will jump to the other window. Then, set focus to the proper
	// form element and select the text inside.
	
	var toolbar = getToolbar();
	
	if (toolbar == null) return; // short-circuit
	
	var contentWindow = toolbar.getWindow();
	
	contentWindow.focus();
	
	// Convert the form and form field indexes into object references.
	
	var form = contentWindow.document.forms[formIndex];
	
	// We'll loop over the form fields starting with the specified index. We'll
	// attempt to set focus on each form element.
	
	for (var i = fieldIndex; i < form.elements.length; i++)
	{
		
		var field = form.elements[i];
		
		// Try to set focus on the form field. This will throw an error in IE if
		// the object isn't visible. This will be the case if the user
		// collapsed a label. In which case, we'll set focus on the next visible
		// element.
		
		// Unfortunately, Firefox doesn't throw an error or return a result. It
		// just silently fails. There doesn't appear to be a way to tell whether
		// or not focus was actually set in Firefox. So, if the form element is
		// hidden, no form elements will get focus in Firefox.
		
		try
		{
			
			field.focus();
			
			// Not all form fields have a select method. It's impossible to
			// select the text in a select list, for instance.
			
			if (field.select)
			{
				field.select();
			}
			
			// If we made it this far, we successfully set focus on a form
			// element without throwing an error. We can break out of the
			// loop.
			
			break;
			
		}
		catch(e)
		{
			// Ignore any errors. Assume the field was hidden and the call to
			// focus() threw an error.
		}
		
	}
	
}


function isTrue(value) {
	
	if ( value == null ) {
		
		return false;
		
	} else if ( value == true ) {
		
		return true;
		
	} else if ( value == "true" ) {
		
		return true;
		
	} else if ( value == "yes" ) {
		
		return true;
		
	} else if ( value == "1" ) {
		
		return true;
		
	} else if ( value == 1 ) {
		
		return true;
		
	} else {
		
		return false;
		
	}
	
}

// Declare global variables that will be used for highlighting records. These
// are references to the currently highlighted row and that row's class before
// it was swapped for the highlighted class.

var highlightedRowOriginalClass;
var highlightedRow;

function highlightRow(rowToHighlight) {
	
	// If we already have a highlighted row, we need to restore it's original
	// class.

	// void operator returns undefined in a manner consistent with the
	// JavaScript implementation.
	
	if ( highlightedRow ) {
		
		highlightedRow.className = highlightedRowOriginalClass;
		
	}
	
	// Record a reference to the original row so that we can identify it when we
	// go to restore the original class.
	
	highlightedRow = rowToHighlight;
	
	// Record the class on the row we're about to highlight so that we can
	// restore it.
	
	highlightedRowOriginalClass = highlightedRow.className;
	
	// Change the class so that the row now appears highlighted.
	
	highlightedRow.className = "DataGridHighlightedRow";
	
	
	
}


function toggleAdvancedOptions(buttonObj) {

	toggleDisplay('AdvancedLimit', 'AdvancedFields', 'TranslateColumnHeadersOption');
	
}

function handleDownloadFormatSelection(radio) {
	
	setHide('IncludeColumnHeadersOption', 'EndOfLineCharacterOption')
	
	switch ( radio.value ) {
	
		case "Print":
			
			if ( radio.checked ) {
				
				radio.form.action = 'Print.aspx';
				radio.form.target = '_blank';
				radio.form.Action.value = 'Print';
				
				
			}
			
			break;
		
		case "AdvancedPrint":
			
			if ( radio.checked ) {
				
				radio.form.action = 'Print.aspx';
				radio.form.target = '_blank';
				radio.form.Action.value = 'AdvancedPrint';
				
			}
			
			break;
		
		case "CSV":
			
			if ( radio.checked ) {
				
				radio.form.action = 'Download.aspx';
				radio.form.target = 'download';
				radio.form.Action.value = 'Download';
				setDisplay('IncludeColumnHeadersOption', 'EndOfLineCharacterOption')
				
			}
			
			break;
		
		case "XML":
			
			if ( radio.checked ) {
				
				radio.form.action = 'Download.aspx';
				radio.form.target = 'download';
				radio.form.Action.value = 'Download';
				setDisplay('IncludeColumnHeadersOption', 'EndOfLineCharacterOption')
				
			}
			
			break;
		
		case "FixedWidth":
			
			if ( radio.checked ) {
				radio.form.action = 'Download.aspx';
				radio.form.target = 'download';
				radio.form.Action.value = 'Download';
				setDisplay('IncludeColumnHeadersOption', 'EndOfLineCharacterOption')
			}
			
			break;
			
		case "Excel":
			
			if ( radio.checked ) {
				radio.form.action = 'Download.aspx';
				radio.form.target = 'download';
				radio.form.Action.value = 'Download';
			}
			
			break;
			
		case "Word":
			
			if ( radio.checked ) {
				radio.form.action = 'Print.aspx';
				radio.form.target = 'download';
				radio.form.Action.value = 'Download';
			}
			
			break;
			
	}
	
}

function pageChange(clickedElement) {
	if ( clickedElement.style != null ) {
		
		clickedElement.style.cursor = "wait";
		
	}
	
	document.body.style.cursor = "wait";
	
}

function OnClickLink(href) {
	window.location.href = href;
	return false;
}


function reloadPage()
{
	
	// Get a reference to the content window frame from the toolbar collection.
	// We're using this method so that reloadPage() can be called from the
	// toolbar, which is in a different frame.
	
	var toolbar = getToolbar();
	
	var contentWindow = toolbar.getWindow();
	
	// Record the current label states. Instead of passing in a specific
	// SessionHistoryID, we'll use zero, which is a special value denoting the
	// current SessionHistoryID. This is done because, unless SessionHistoryID
	// is in the the URL, the next request will up with a new SessionHistoryID.
	
	recordLabelStates(0);
	
	// Finally, issue the reload.
	
	contentWindow.document.location.reload();
	
}

// This function sends the user to the previous page using the history.back()
// function. It's a fall back for the CranBerry back button. It is called when
// there is no session history to fall back on.
// 
// This function records the current label states before issuing the call to
// history.back(). This way, when the user navigates back to this page, the
// groups will be in the same state the user left them.
// 
// Please note that this is an obscure issue. In most situations, CranBerry will
// direct the user to an explicit URL. In which case, this function will not get
// called. However, there are a few situations where the user could find
// themselves on a vertical page without session history. In particular, if the
// user has been logged out of their session while sitting on a vertical page,
// they will be returned to that vertical page and their session history will
// have been wiped out.
//   
// Also, the user must change the state of one or more labels. If the user does
// not change the label state, then there's nothing interesting to preserve.

function previousPage()
{
	
	var toolbar = getToolbar();
	
	var contentWindow = toolbar.getWindow();
	
	recordLabelStates(0);
	
	contentWindow.history.back();
	
}

// Returns a reference to the toolbar interface stored in the frameset's
// navigator object.

function getToolbar()
{
	return (window.parent.navigator._toolbars != null) ? window.parent.navigator._toolbars["Toolbar"] : null;
}

/******************************************************************************
 **********                      Label/Groups                        **********
 ******************************************************************************/

// This function scans the document for empty groups. If it finds an empty
// group, it hides the label and the group content. Empty groups are still
// included in the page because group states are based off the index. So, if we
// removed a group from the actual document object model, it would skew the
// group state index.

function checkLabels()
{
	
	var labels = getElementsByClassName("DataGridGroupRow");
	
	for (var i in labels)
	{
		
		var label = labels[i];
		
		var groupID = label.getAttribute("cb:labelforfieldset");
		
		var group = document.getElementById(groupID);
		
		// NOTE: We're checking for TDs instead of TRs because the vertical
		// formatter writes out 1 empty tr.
		
		var cells = group.getElementsByTagName("TD");
		
		if (cells.length == 0)
		{
			hide(label);
			hide(group);
		}
		
	}
	
}
function toggleFieldSetDisplay(sessionHistoryID, groupID, collapsedIconSrc, expandedIconSrc) {
	var group = getObject(groupID);
	var cell = getObject("cell_" + groupID);
	var icon  = getObject("groupIcon_" + groupID);
	var isExpanded = ("1" == cell.getAttribute("cb:fieldsetstate"));
	
	if (isExpanded)
		hide(group);
	else
		display(group);
		
	icon.src = isExpanded ? collapsedIconSrc : expandedIconSrc;
	cell.setAttribute("cb:fieldsetstate", (isExpanded ? "0" : "1"));
		
	// Now that we've change the group's state, we'll associate them with this
	// page's SessionHistoryID and persist them. Note that the sessionHistoryID
	// variable is a global variable.
	recordLabelStates(sessionHistoryID);
	

}


// Records the label states of the current vertical view to a cookie. The states
// are associated with an arbitrary ID. Generally, this will be the
// SessionHistoryID, which is available as a global variable. However, it could
// be 0, which is a special value that tells the server to associate the label
// states with the current SessionHistoryID, whatever that might be. This is
// useful for page reloads where you want to preserve the label states but do
// not necessarilly know the SessionHistoryID because it may not be set yet.

function recordLabelStates(id) {
	var labels = getElementsByClassName("DataGridGroupRow");
	
	var states = new Array();
	
	for (var i in labels) {
		
		var label = labels[i];
		
		var currentState = label.getAttribute("cb:fieldsetstate");
		
		states.push(currentState);
	}
	
	var labelStates = getLabelStates();
	
	// This both adds the state for the current session history ID and
	// overwrites any existing value.
	
	labelStates[id] = states;
	
	persistLabelStates(labelStates);
	
}

// Returns a collection (hash table) of label states indexed by session history
// ID. The label states are stored in an array. The following is an example of
// the structure:
//   
//   { "99998" : [0,1,0], "99999" : [0,1,0] }
//   
// The states are read from the LabelStates cookie, which is in the
// following form:
//   
//   99998:0,1,0;99999:1,1,1

function getLabelStates()
{
	
	var stateCollection = { };
	
	// label states are stored in a cookie in the following form:
	//   
	//   99998:0,1,0;99999:1,1,1
	
	var cookie = CookieManager.getCookie("FieldSetStates") || "";
	
	var nameValuePairs = cookie.split(";");
	
	for (var i in nameValuePairs)
	{
		
		var nameValuePair = nameValuePairs[i];
		
		if (nameValuePair != "")
		{
			
			var nameValuePairArray = nameValuePair.split(":");
			
			var sessionHistoryID = nameValuePairArray[0];
			
			var states = nameValuePairArray[1].split(",");
			
			stateCollection[sessionHistoryID] = states;
			
		}
		
	}
	
	return stateCollection;
	
}

// Takes a collection (hash table) of label states indexed by session history
// ID and persists them to a cookie named LabelStates. The data structure should
// take the following form:
//   
//   { "99998" : [0,1,0], "99999" : [0,1,0] }
//   
// The cookie value will be formatted as such:
//   
//   99998:0,1,0;99999:1,1,1

function persistLabelStates(pages)
{
	
	var cookie = "";
	
	for (var pageID in pages)
	{
		
		if (cookie != "")
		{
			cookie += ";";
		}
		
		var labelStates = pages[pageID];
		
		cookie += pageID + ":" + labelStates.join();
		
	}
	
	CookieManager.setCookie("FieldSetStates", cookie, null, null, "");
	
}

function getElementsByClassName(className, tagName, rootNode) {
	
	// If no tag name has been specified, default to the wildcard.
	
	tagName = tagName || "*";
	
	// If no root node has been defined, default to the document object.
	
	rootNode = rootNode || document;
	
	// Get a collection of candidates.
	
	// NOTE: This will not work in IE 5 and under. IE 5 does not support the
	// wildcard character. IE 4 does not support getElementsByTagName(). In
	// these browsers, you must use document.all and document.all.tags.
	
	var elements = rootNode.getElementsByTagName(tagName);
	
	// Create an array in which we'll store our matches.
	
	var matches = new Array();
	
	// The className property is a string consisting of class names separated by
	// spaces. We'll build a regex to match this pattern.
	
	var regEx = new RegExp("(?:^|\\s+)" + className + "(?:\\s+|$)");
	
	for (var i = 0; i < elements.length; i++)
	{
	
		var currentElement = elements[i];
		
		if (regEx.test(currentElement.className))
		{
			matches.push(currentElement);
		}
		
	}
	
	return matches;
	
}


//This functions implements maxlength on TextAreas
function validateTextArea(objEvent, objField) {
	reCrLf    = /\r\n/g;
	reNewLine = /\n/g;
	
	if (objField.value.search(reCrLf) == -1) {
		strTest = objField.value.replace(reNewLine,'\r\n');
	} else {
		strTest = objField.value;
	}

	if (strTest.length+1 > objField.getAttribute('cb:maxlength') &&
					(objEvent.keyCode != 8) && //Backspace
					(objEvent.keyCode != 46)) //Del
	{
		return false;
	}
}

function popupCalendar(objField) {
	_objModalDialog.fieldPlaceHolder = objField;
	_objModalDialog.Show("DateTimePicker.aspx?proceed=" + escape(_datagridConstantProceed) + "&clear=" + escape(_datagridConstantClear) + 
	"&mode=date&pattern=" + escape(objField.getAttribute('cb:validatepattern'))+
	"&indate=" + escape(objField.value),
	200,200,'_objModalDialog.setFieldToResult()',0,0,0);
//	_objModalDialog.Show("ClientScripts/CalendarFrame.aspx?proceed="+escape(_datagridConstantProceed)+"&clear="+escape(_datagridConstantClear)+"&mode=date&pattern="+escape(objField.getAttribute('cb:validatepattern'))+"&indate="+escape(objField.value),350,250,'_objModalDialog.setFieldToResult()',0);
}

function popupCalendarClock(objField) {
	_objModalDialog.fieldPlaceHolder = objField;
	_objModalDialog.Show("DateTimePicker.aspx?proceed=" + escape(_datagridConstantProceed) + "&clear=" + escape(_datagridConstantClear) + 
	"&mode=datetime&pattern=" + escape(objField.getAttribute('cb:validatepattern')) + 
	"&indate=" + escape(objField.value),
	250, 200, '_objModalDialog.setFieldToResult()', 0,0,0);
//	_objModalDialog.Show("ClientScripts/CalendarFrame.aspx?proceed="+escape(_datagridConstantProceed)+"&clear="+escape(_datagridConstantClear)+"&mode=datetime&pattern="+escape(objField.getAttribute('cb:validatepattern'))+"&indate="+escape(objField.value),400,250,'_objModalDialog.setFieldToResult()',0);

}

function popupClock(objField) {
	_objModalDialog.fieldPlaceHolder = objField;
	_objModalDialog.Show("DateTimePicker.aspx?proceed=" + escape(_datagridConstantProceed) + "&clear=" + escape(_datagridConstantClear) + 
	"&mode=time&pattern=" + escape(objField.getAttribute('cb:validatepattern')) + 
	"&indate=" + escape(objField.value) + "&hours=" + objField.getAttribute('cb:hours'),
	50, 200, '_objModalDialog.setFieldToResult()',0,0,0);
//	_objModalDialog.Show("ClientScripts/SelectTimeFrame.aspx?proceed="+escape(_datagridConstantProceed)+"&clear="+escape(_datagridConstantClear)+"&mode=time&pattern="+escape(objField.getAttribute('cb:validatepattern'))+"&intime="+escape(objField.value)+"&hours="+objField.getAttribute('cb:hours'),125,275,'_objModalDialog.setFieldToResult()',0);
}

function popupEditor(objField) {	
	document.body.style.cursor = "wait";	
	_objModalDialog.fieldPlaceHolder = objField;
	if(objField.name == "")
	{
	    objField.name = objField.id;
	}	
	_objModalDialog.Show("ClientScripts/Editor.aspx?homepath="+escape(_datagridConstantHomepath)+"&infield="+escape(objField.name),580,794,'popupEditorCallback()',0);
	
//	_objModalDialog.Show(_datagridConstantHomepath + "ClientScripts/Editor.asp?homepath="+escape(_datagridConstantHomepath)+"&infield="+escape(objField.name),580,794,'popupEditorCallback()',0);
//	_objModalDialog.Show(_datagridConstantHomepath + "ClientScripts/Editor.asp?homepath="+escape(_datagridConstantHomepath)+"&infield="+escape(objField.name),380,594,'popupEditorCallback()',0);
}

function popupEditorCallback() {
	obj = document.getElementById(_objModalDialog.fieldPlaceHolder.name);
	
	if (''+_objModalDialog.resultVal != 'undefined' && ''+_objModalDialog.resultVal != 'null') {	    
	    document.getElementById(_objModalDialog.fieldPlaceHolder.name).value = _objModalDialog.resultVal;	    	    
		document.getElementById('Display.' + obj.id).innerHTML = _objModalDialog.resultVal;
	}	
	_objModalDialog.setFieldToResult();

	document.body.style.cursor = "auto";
	
	// This fires the onchange event for the textarea so that it saves the changes properly
	var fakeEvent = new Object({ type : "change", srcElement : obj });
	OC(obj, fakeEvent);	
}

function showAudit(url) {

	popupWindow(url, 400, 600);
	return false;

}

function popupWindow(url, height, width) {

	_objModalDialog.Show(url, height, width, "", 1, true);

}

function popupWindowNoMenu(URL,height,width) {

	_objModalDialog.Show(URL,height,width,"",1);

}


function getCenterPopupWindowLeft(wnd_width) {

    return screen.width/2 - wnd_width/2;
}


function getCenterPopupWindowTop(wnd_height) {

    return screen.height/2 - wnd_height/3;
}

function onHorizontalMenuReady() {
        // Instantiate and render the menu bar
        var oMenuBar = new YAHOO.widget.MenuBar("YUIHorizontalMenu", 
        { 
            autosubmenudisplay  : true, 
            hidedelay           : 750,
            position            : "dynamic",
            visible             : true,
            constraintoviewport : true,
            lazyload            : false /* otherwise will initially wrap in IE :( */
         }); 
         
       oMenuBar.setInitialFocus = function() { };  

       oMenuBar.render();
}
            
function onVerticalMenuReady() {
   // Instantiate and render the menu
   
	var VerticalMenu = document.getElementById("YUIVerticalMenu");
	
	// Fix the width of our vertical menu for IE
	if( BrowserIs_ie )
	{
//		VerticalMenu.style.width = VerticalMenu.parentElement.clientWidth;
	}
	
   var oMenu = new YAHOO.widget.Menu(
                        "YUIVerticalMenu", 
                        {
                            position:"static", 
                            hidedelay:750, 
                            lazyload:true 
                        }
                    );
    oMenu.render();
};

/* This function handles a form save even from the horizontal or vertical
 * view. */

function handleSave(form)
{
	if (!checkForm(form))
	{
		return false;
	}
	
	pageChange(form);
	
	return true;
}

function checkForm(elem) {

	var blNeedsSignature = false;
	var aryCols = new Array();
	var varResult = false;

	if (_datagridConstantFullPageCount > 0)
	{
		for(var row = 1;row<=_datagridConstantFullPageCount;row++)
		{
			for(var i = 0;i<_datagridConstantRequireSignatureCols.length;i++)
			{
				var objEdit = document.getElementById(_datagridConstantEditPrefix + row + "." + _datagridConstantRequireSignatureCols[i])
				var objShadow = document.getElementById(_datagridConstantShadowPrefix + row + "." + _datagridConstantRequireSignatureCols[i])
				if(objEdit.value != objShadow.value) {
					blNeedsSignature = true;
					aryCols[aryCols.length] = _datagridConstantRequireSignatureCols[i];
				}
			}
		}
	}
	else
	{
		for(var i = 0;i<_datagridConstantRequireSignatureCols.length;i++)
		{
			var objEdit = document.getElementById(_datagridConstantEditPrefix + _datagridConstantRequireSignatureCols[i])
			var objShadow = document.getElementById(_datagridConstantShadowPrefix + _datagridConstantRequireSignatureCols[i])
				
			if(objEdit.value != objShadow.value) {
				blNeedsSignature = true;
				aryCols[aryCols.length] = _datagridConstantRequireSignatureCols[i];
			}
		}
	}

	var objSignatureField = document.getElementById('SignatureToken')

	if (blNeedsSignature && objSignatureField.value == '') {

		var varProcessToken = document.getElementById('ProcessToken').value
		var varPageID =  document.getElementById('PageID').value
		if (_datagridConstantFullPageCount == 0)
		{
			var objSave = document.getElementById('Save')
			
			//Dither and disable save image. Submit will be handled by the popup.
			objSave.style.cssText = 'filter:alpha(opacity=30);-moz-opacity:0.3;opacity: 0.3;'
			objSave.disabled = true;
		}
		_objModalDialog.Show('ClientScripts/ElectronicSignatureFrame.aspx?ProcessToken='+varProcessToken+'&PageID='+varPageID+'&cols='+aryCols.join('&cols='),400,400,null,0);

	} else {

		varResult = true;
	}

	//Elem.style.cursor = null;
//	document.body.style.cursor = null;
	
	return(varResult);
}

function receiveSignature(strToken, strComment) {
	document.getElementById('SignatureToken').value = strToken
	document.getElementById('SignatureComment').value = strComment
	document.getElementById('SignatureToken').form.submit();
	
}

function toggleDump(i) {
	
	toggleDisplay("DumpValue_" + i, "DumpNested_" + i);
	
}

/******************************************************************************
 **********                       Accessor Keys                      **********
 ******************************************************************************/

// Checks the event to see if the user pressed ctrl+s. If so, the specified form
// will be saved.

function saveForm(event, formName)
{
	
	event = event || window.event;
	
	var modifierKeys = event.ctrlKey && !event.altKey && !event.shiftKey;
	
	if (modifierKeys && event.keyCode == 83)
	{
		
		//Cancel propagation of the event. ctrl+s is Save Page in Firefox
		//Doing this cancels further browser interpretation of the event.
		
		//IE
		event.cancelBubble = true;
		event.returnValue = false;
		//Firefox
		if (event.stopPropagation) {
			event.stopPropagation();
			event.preventDefault();
		}
		
		var form = document.forms[formName];
		
		if (form)
		{
			var formIndex;
			for ( formIndex = 0; formIndex < document.forms.length; formIndex++ ) {
				var form1 = document.forms[formIndex];
				if (form1.name == formName) {
					break;
				}
			}

			var submit = eval("objForm_" + formIndex + ".submitCheck();"); 
			if (submit) {
				form.submit();
			}
		}
		
	}
	
}

function sortColumn(event, column, ascendingUrl, descendingUrl, toggleUrl)
{
	
	event = event || window.event;
	
	pageChange(column);
	
	// Check to see if the control key (and only the control) was depressed when
	// the column was clicked. If so, we will sort in ascending order.
	
	var ascendingModifiers = event.ctrlKey && !event.altKey && !event.shiftKey;
	
	if (ascendingModifiers)
	{
//		alert("Ascending Sort");
		window.location.href = ascendingUrl;
		return;
	}
	
	// Check to see if the control and alt keys were depressed when the column
	// was clicked. If so, we'll sort descending.
	
	var descendingModifiers = event.ctrlKey && event.altKey && !event.shiftKey;
	
	if (descendingModifiers)
	{
//		alert("Descending Sort");
		window.location.href = descendingUrl;
		return;
	}
	
	// If we made it this far, then there were no recognized key modifiers in
	// effect. In which case, we'll toggle the sort.
//	alert("Toggle Sort");
	window.location.href = toggleUrl;
	
}

/* ----------------------------------------------------------------------------------------------------------------*/
/* ----------------------------------------->>> Global PageMethods <<<---------------------------------------------*/
/* ----------------------------------------------------------------------------------------------------------------*/
var PageMethods = {

    __messageList: [],

    postMessage: function(s) {
        this.__messageList.push(s);
    },
    
    raiseMessageAlerts: function() {
        for(var i = 0; i < this.__messageList.length; i++)
            window.alert(this.__messageList[i]);
    },
    
    init: function() {
        this.__resizePageContentAreaSpacerImageHeight();
    },
    
    __resizePageContentAreaSpacerImageHeight: function() {
        
        // This method changes the height of the DataGrid cell spacer image 
        // to match the height of the vertical menu.  If either element is
        // not found, the operation has no effect.
        
        // This hack depends on that horrible naming container which mangles 
        // the IDs assigned to elements, hence the ctl00 garbage.
    
        var el = document.getElementById("PageContentAreaSpacerImage");
        var td = document.getElementById("ctl00_MenuTD");
        
        if(el != null && td != null)
        {        
            if(td.offsetHeight > 350) {
                el.height = td.offsetHeight;
            }
        }
    },        

    last_member: 0
};

/*********************************************************************************/
/* Deferred Record Count                                                         */
/*********************************************************************************/

var RecordCount = { 
 
    handleSuccess:function(o){ 
        if(o.responseText !== undefined && o.responseText !== 'error'){
            document.getElementById('RecordCountArea').innerHTML = o.responseText; 
         } 
    }, 
 
    handleFailure:function(o){ 
    }, 
 
    getRecordCount:function(sParms) { 
       YAHOO.util.Connect.asyncRequest('POST', 'DeferredRecordCount.aspx', recordCountCallback, sParms); 
    } 
 
}; 
 
var recordCountCallback = 
{ 
    success:RecordCount.handleSuccess, 
    failure:RecordCount.handleFailure, 
    scope: RecordCount 
};



/*********************************************************************************/
/* Column Hover View                                                              */
/*********************************************************************************/

_column_hoverview_timeout = null;

function clearColumnHoverViewTimeout() {
	if ( _column_hoverview_timeout != null ) {
		window.clearTimeout(_column_hoverview_timeout);
		_column_hoverview_timeout = null;
	}
}

function OnColumnHoverviewCallback(URL, Control) {
	YAHOO.util.Connect.asyncRequest('GET', URL, CreateColumnHoverviewCallback(Control));
}

function CreateColumnHoverviewCallback(Control) {
		var callback = {success:ReceiveColumnHoverviewData,
		                failure:ProcessColumnHoverviewCallBackError,
		                argument: { control:Control }
		               };
		return callback;
}

function ReceiveColumnHoverviewData(o) {
	_column_hoverview_timeout = null;
	if (o.responseText !== undefined) {
		if (o.argument.control !== undefined) {
			o.argument.control.TableCell.PopupText = "stop";
			o.argument.control.cfg.setProperty ( "text", o.responseText, true );
			o.argument.control.cfg.setProperty ( "showdelay", 1000, true );
			o.argument.control.cfg.setProperty ( "hidedelay", 2000, true );
			o.argument.control.cfg.setProperty ( "disabled", false, true );
			o.argument.control.doShow( null, this.context );
    		
    		highlightRow(o.argument.control.TableCell.parentNode);
		}
	}
}

function ProcessColumnHoverviewCallBackError(arg, context) {
	_column_hoverview_timeout = null;
	if(o.responseText !== undefined) {
		if (o.argument.control !== undefined) {
			o.argument.control.title = o.statusText;
        }
	}
}

function columnHoverviewToolTipData(e, queryString, tableCell) {
    if(!e) e = window.event;
    var oRelatedTarget = e.relatedTarget;
    if ( !oRelatedTarget ) { oRelatedTarget = e.toElement; }
    
    if ( !isChild( this, oRelatedTarget ) ) {
    	if ( !tableCell.PopupText )	{
            var xPosition = YAHOO.util.Event.getPageX(e);
            var yPosition = YAHOO.util.Event.getPageY(e);
    		var Index = 0;
    		columnHoverviewToolTipControls[Index] = new YAHOO.widget.Tooltip("columnHoverviewToolTipControls[" + Index + "]", { context:tableCell.id, xy: [xPosition,yPosition], disabled: true, showdelay:0,autodismissdelay:200000,effect:{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.15} } );
		    columnHoverviewToolTipControls[Index].TableCell = tableCell;
    		var func = function(){OnColumnHoverviewCallback(queryString, columnHoverviewToolTipControls[Index])}
    		_column_hoverview_timeout = window.setTimeout(func, 500);
    	}
    	else	
   		    highlightRow(tableCell.parentNode); // we've already got the text, just highlight the row
	}
}

function columnHoverviewToolTipDataOut(e) {
    if(!e) e = window.event;
    var oRelatedTarget = e.relatedTarget;
    
    if ( !oRelatedTarget ) { oRelatedTarget = e.toElement; }
    if ( !isChild( this, oRelatedTarget ) ) {    
 	    clearColumnHoverViewTimeout();
 	}
}

function isChild( oParent, oChild ) {
    var bReturn = false;
    var oObj = oChild;
    while ( oObj != null ) {
        if ( oObj == oParent ) {
            bReturn = true;
            break;
        }
        oObj = oObj.parentNode;
    }
    return bReturn;
}


/*********************************************************************************/
/* Title Hover View                                                              */
/*********************************************************************************/

var TitleHoverView = { 

    titleHoverViewAreaTooltip : null,
    
    handleSuccess:function(o){ 
        if(o.responseText !== undefined && o.responseText !== 'error' && this.mouseOutFired == false){
            this.titleHoverViewAreaTooltip = new YAHOO.widget.Tooltip('titleHoverViewAreaTooltip', { context:'TitleHoverViewArea', autodismissdelay:2000, visible: true, xy: this.positionXY, text:o.responseText } ); 
            this.titleHoverViewAreaTooltip.doShow(null, this.context);           
        }
        var helloWorld = function(e) { 
	        alert("Hello World!"); 
	       }  
           jsLog(YAHOO.util.Event.addListener(this.titleHoverViewAreaTooltip, "mouseover", helloWorld));
        
    }, 
    
    handleFailure:function(o){ 
        jsLog('TitleHoverView.handleFailure');
    }, 
 
    getTitleHoverView:function(sParms) { 
        this.mouseOutFired = false;
        // this.titleHoverViewAreaTooltip.addOnMouseOver();
         /*  if (document.getElementById('titleHoverViewAreaTooltip') != null)
           {
                var hover = document.getElementById('titleHoverViewAreaTooltip');
                
                hover.onmouseover = "alert('Surprise!')";
           } */
                       
           //YAHOO.util.Event.addListener(this.titleHoverViewAreaTooltip, "mouseout", helloWorld);
           //YAHOO.util.Event.addListener(this.titleHoverViewAreaTooltip, "click", helloWorld);
           // this.titleHoverViewAreaTooltip.toString();
           
        try{
            if (this.titleHoverViewAreaTooltip != null && this.titleHoverViewAreaTooltip !== undefined && this.titleHoverViewAreaTooltip.cfg != null){                
                this.titleHoverViewAreaTooltip.doHide(null, this.context);
                this.titleHoverViewAreaTooltip.destroy();
            }
        } catch (e) {}
        
        // grab the highlighted row
        var highlightedRow = YAHOO.util.Dom.getElementsByClassName("DataGridHighlightedRow");
        if (highlightedRow.length > 0){
            sParms += '&' + highlightedRow[0].getAttribute("cb_key");
        } else {
            keyFields = YAHOO.util.Dom.getElementsBy(elementHasKey, "tr");
            sParms += '&' + keyFields[0].getAttribute("cb_key");
        }
        
        YAHOO.util.Connect.asyncRequest('POST', 'TitleHoverView.aspx', titleHoverViewCallback, sParms);         
    },
    
    removeHoverView:function(){
        this.mouseOutFired = true;
        hover = document.getElementById('titleHoverViewAreaTooltip');
       
        if (hover != null && hover !== undefined){            
            hover.visible = false;
        }
    },
    
    positionXY: null,
    
    mouseOutFired: false
    
}; 
 
var titleHoverViewCallback = 
{ 
    success:TitleHoverView.handleSuccess, 
    failure:TitleHoverView.handleFailure, 
    scope: TitleHoverView     
};

// NATHAN for hover panel
  var m_xmlHTTPRequest = null; 
  var m_showHoverTimeout = 0;
  var m_hideHoverTimeout = 0;
  var m_firingSource = "";

function requestShowHover(e, eventTarget, params, interval)
{   
    if((m_showHoverTimeout != 0 || m_hideHoverTimeout != 0) && document.getElementById("hoverPanel").style.display != "block")
    {
       clearTimeout(m_showHoverTimeout);
       m_showHoverTimeout = 0;
    }
    else
    {            
        m_showHoverTimeout = setTimeout("showHoverPanel('" + eventTarget + "','" +  params + "');m_showHoverTimeout=0;", interval);
        m_firingSource = eventTarget;
    }
}

function requestHideHover(e, interval)
{
    if (!e) e = window.event;
    if ( !e.target ) { e.target = e.srcElement; }
    
    var myTarget = e.target;
    
    if((m_hideHoverTimeout != 0 || m_showHoverTimeout != 0) && document.getElementById("hoverPanel").style.display != "block")
    {
       // no hover yet, but a request is pending
       clearTimeout(m_hideHoverTimeout);
       clearTimeout(m_showHoverTimeout);
       m_hideHoverTimeout = 0;
       m_showHoverTimeout = 0;  
    }
    else if((m_hideHoverTimeout != 0 && m_showHoverTimeout != 0) && document.getElementById("hoverPanel").style.display == "block")
    {       
       // we have a hover and both requests are set. 
       clearTimeout(m_showHoverTimeout);
       clearTimeout(m_hideHoverTimeout);
       m_hideHoverTimeout = setTimeout("hideHoverPanel();m_hideHoverTimeout=0;", interval); 
       m_showHoverTimeout = 0;        
    }
    else 
    {        
        clearTimeout(m_hideHoverTimeout);
        m_hideHoverTimeout = setTimeout("hideHoverPanel();m_hideHoverTimeout=0;", interval); 
    }    
}


function createHoverAJAXRequest(eTarget, params)
{    
    if(navigator.appName == "Microsoft Internet Explorer")
    {
        m_xmlHTTPRequest = new ActiveXObject("Microsoft.XMLHTTP");
    } 
    else 
    {
        m_xmlHTTPRequest = new XMLHttpRequest();
    }        
            
    m_xmlHTTPRequest.open('POST','HoverView.aspx', true);
   
    m_xmlHTTPRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    m_xmlHTTPRequest.onreadystatechange = ajaxResponse;
    m_xmlHTTPRequest.send(params);
    jsLog(params);
}

function ajaxResponse() {   
    if(m_xmlHTTPRequest.readyState == 4) 
    {
        document.getElementById("hoverPanel").innerHTML = "";
        document.getElementById("hoverPanel").innerHTML = m_xmlHTTPRequest.responseText;        
        document.getElementById("hoverPanel").style.display = "block";
        document.getElementById("hoverPanel").style.zIndex = 9500; 
    }
}

function cancelHideTimeout()
{
    clearTimeout(m_hideHoverTimeout);
    m_hideHoverTimeout = 0;    
}

function showHoverPanel(eventTarget, params)
{  
    var highlightedRow = YAHOO.util.Dom.getElementsByClassName("DataGridHighlightedRow");  
    if (highlightedRow.length > 0 && highlightedRow[0].getAttribute("cb_key") != null)
    {
        params += '&' + highlightedRow[0].getAttribute("cb_key");
    } 
    else 
    {
        keyFields = YAHOO.util.Dom.getElementsBy(elementHasKey, "tr");
        if(keyFields[0] != null)
        {
            params += '&' + keyFields[0].getAttribute("cb_key");
        }
    }   
        
    createHoverAJAXRequest(eventTarget, params);
    document.getElementById("hoverPanel").style.top = findPosY(eventTarget) + document.getElementById(eventTarget).offsetHeight + 5 + "px"; 
    document.getElementById("hoverPanel").style.left = findPosX(eventTarget) + "px";               
}

function hideHoverPanel()
{
     document.getElementById("hoverPanel").style.display = "none";
     document.getElementById("hoverPanel").innerHTML = "";
}

function findPosX(objName)
{
    var curleft = 0;
    var obj = document.getElementById(objName);
    if (obj != null)
    {
        if(obj.offsetParent)
            while(1) 
            {
              curleft += obj.offsetLeft;
              if(!obj.offsetParent)
                break;
              obj = obj.offsetParent;
            }
        else if(obj.x)
            curleft += obj.x;
    }
    return curleft;
}

function findPosY(objName)
{
    var curtop = 0;
    var obj = document.getElementById(objName);
    if (obj != null)
    {
        if(obj.offsetParent)
            while(1)
            {
              curtop += obj.offsetTop;
              if(!obj.offsetParent)
                break;
              obj = obj.offsetParent;
            }
        else if(obj.y)
            curtop += obj.y;
    }
    return curtop;
}
  
  
function cancelEvent(event) {
    if ( !event ) {
      event = window.event;
    }

    event.returnValue = false;

    if ( event.cancelBubble ) {
    event.cancelBubble = true;
    } 

    if (event.stopPropagation) {
     event.stopPropagation();
    }

    if ( event.preventDefault ) {
    event.preventDefault();
    }

    if ( window.event ) {
    window.event.cancelBubble=true;
    }

    return false;
}


