/*
** Methods for dragging the centre div to change the widths of the two display divs
*/

var startPosition=0;
var capturedByDivider = false;
var initialLeftWidth = 0
var initialRightWidth = 0;

var currentFieldResizer = null;

function dataExplorerDividerMouseDown(Event)
{
    startPosition = getMouseX(Event);        
    capturedByDivider = true;
    var leftDiv = document.getElementById("dataExplorerLeftDiv");
    var rightDiv = document.getElementById("dataExplorerRightDiv");
    initialLeftWidth = leftDiv.offsetWidth;
    initialRightWidth = rightDiv.offsetWidth;

    return false;
}

function dataExplorerDividerMouseUp(Event)
{
    capturedByDivider = false;
    return false;
}

function dataExplorerDividerMouseMove(Event)
{
    var newPosition;
    var difference
    var leftDiv;
    var rightDiv;
    var finalLeftWidth; 
    var finalRightWidth; 
    
    if (capturedByDivider)
    {
        leftDiv = document.getElementById("dataExplorerLeftDiv");
        rightDiv = document.getElementById("dataExplorerRightDiv");
        
        newPosition = getMouseX(Event);        
        difference = startPosition-newPosition;

        finalLeftWidth = initialLeftWidth - difference;
        finalRightWidth = initialRightWidth + difference;

        if (finalLeftWidth>20 && finalRightWidth>20)
        {
            leftDiv.style.width = finalLeftWidth + "px";
            rightDiv.style.width = finalRightWidth + "px";
        }
    }
}


function setDataExplorerDividerEvents()
{
    var spacer = document.getElementById("dataExplorerSpacerDiv");

    addEventHandler(spacer, "mousedown", dataExplorerDividerMouseDown);
    addEventHandler(document, "mouseup", dataExplorerDividerMouseUp);
    addEventHandler(document, "mousemove", dataExplorerDividerMouseMove);

    addEventHandler(document, "mousedown", dragdropFieldMouseDown);
    addEventHandler(document, "mouseup", dragdropFieldMouseUp);
    addEventHandler(document, "mousemove", dragdropFieldMouseMove);
    
}

function dragdropFieldMouseDown(Ev)
{
    return dragdropMouseDown(Ev);
}

function dragdropFieldMouseMove(Ev)
{
    return dragdropMouseMove(Ev);
}

function dragdropFieldMouseUp(Ev)
{
    dragdropCallbackObject = new dragdropCallback();    
    dragdropCallbackObject.onMouseUpCallback = function(field)
    {
        var Ajax = new sack("datastructurerepositionfield.mth"); 

        var existingPosition = field.getAttribute("position");
        var prefix = field.getAttribute("controlprefix");
        var uniqueFieldID = field.getAttribute("uniquefieldid");
        var explorerStateElement  = document.getElementById(prefix+".dataexplorerstateid");
        var explorerStateID = explorerStateElement.value;
        /* Notify the server that the size of a field has changed */
//        trace("onMouseUpCallback... uniquenodeid = "+ uniqueFieldID);

        var newPosition = 0;
        var parent = field.parentNode;
        var children = getChildren(parent);
        var numChildren = children.length;
        var childIdx;
        var position=0;
        for (childIdx = 0; childIdx<numChildren; childIdx++)
        {
            var child = children[childIdx];
            if (child.className == "fieldgroupfield")
            {
                var childUniqueFieldID = child.getAttribute("uniquefieldid");
                if (childUniqueFieldID == uniqueFieldID)
                {
                    newPosition = position;
                    break;
                }
                position++;
            }
        }

        position = 0;
        for (childIdx = 0; childIdx<numChildren; childIdx++)
        {
            var child = children[childIdx];
            if (child.className == "fieldgroupfield")
            {
                child.setAttribute("position", position);
            
                var propertyId = child.id+".properties";
                var propertySheet = document.getElementById(propertyId);
                propertySheet.style.left = child.style.left;
                position++;
            }
        }

        Ajax.setVar(prefix+".dataexplorerstateid",explorerStateID);  
        Ajax.setVar("existingposition",existingPosition);  
        Ajax.setVar("newposition",newPosition);  
        Ajax.setVar("uniquefieldid",uniqueFieldID);  
        
        Ajax.onCompletion = function DoNothing() 
        { 
        };
        
        Ajax.runAJAX(); 
    
    };
    
    var Result = dragdropMouseUp(Ev);
    dragdropCallbackObject = null;
    return Result;
}



function trace(narrative)
{
    document.getElementById("debugoutput").innerHTML=narrative;
}

/*
** Methods to notify the server of a change of state of a field inclusion
*/

function dataexplorerIncludeField(uniqueNodeID, prefix) 
{ 
    var Ajax = new sack("datastructureincludefield.mth"); 
    
    var explorerStateElement  = document.getElementById(prefix+".dataexplorerstateid");
    var explorerStateID = explorerStateElement.value;
    
    var includeFieldElement = document.getElementById("INCLUDEFIELD:"+uniqueNodeID);
    var included = includeFieldElement.checked;

    Ajax.setVar("uniquenodeid",uniqueNodeID);  
    Ajax.setVar(prefix+".included",included);  
    Ajax.setVar(prefix+".dataexplorerstateid",explorerStateID);  
    
    Ajax.onCompletion = function populateIncludedFields() 
    { 
        var XMLNode = this.xmlhttp.responseXML.selectSingleNode("/ajax"); 
        if (XMLNode)
        {
/*            alert(getXMLNodeListSerialisation(XMLNodeList1)); */
            var elementObj1 = getFieldGroupContainer(); 
            reflectFieldChanges(XMLNode, elementObj1, uniqueNodeID)
//            replaceDOMChildren(XMLNodeList1, elementObj1);  
        }
        dataexplorerCreateDragContainers();
        dataexplorerCreateFieldResizers();
        resizeRightDiv();
        dataexplorerSizeRightDivs();
    };
      
    Ajax.runAJAX(); 
};

function reflectFieldChanges(xmlNodeParent, domNodeParent)
{
    /* domNode and xmlNode are two parallel trees, but the xmlNodeList has either had one field added or removed.
    Each field can will contain 2 divs, one for the field display, and one for the filters/sort.
     
    This change needs to be reflected in the dom */
    
    
    var xmlNodeList = getChildren(xmlNodeParent);
    var domNodeList = getChildren(domNodeParent);
    var xmlNodeListCount = xmlNodeList ? xmlNodeList.length : 0;
    var domNodeListCount = domNodeList ? domNodeList.length : 0;
    var childIdx;
    var xmlNodeChild;
    var domNodeChild;
    var fragment;
    
    if (xmlNodeListCount == domNodeListCount)
    {
        for (childIdx = 0; childIdx < xmlNodeListCount; childIdx++)
        {
            xmlNodeChild = xmlNodeList[childIdx];
            domNodeChild = domNodeList[childIdx];

            /* limit recursion by identifying when we have got to a field or property sheet */
            
            var recursionLimitReached = false;
            if ( (xmlNodeChild.nodeType != 3) && (xmlNodeChild.tagName.toLowerCase() == "div"))
            {
                var className = xmlNodeChild.getAttribute("class");
                if (className)
                {
                    if ((className == "fieldgroupfield") || (className == "dataexplorerpropertysheet"))
                    {
                        recursionLimitReached = true;
                    }
                    if (className == "fieldgroupfields")
                    {
                        domNodeChild.style.width = calculateWidth(xmlNodeChild)+"px";
                    }
                }
            }

            if (!recursionLimitReached)
            {
                reflectFieldChanges(xmlNodeChild, domNodeChild);
            }
        } 
    }
    else
    {
        if (xmlNodeListCount > domNodeListCount)
        {
            /* an added field, mnust be at the end*/
            for (childIdx = domNodeListCount; childIdx < xmlNodeListCount; childIdx++)
            {
                var addedField = xmlNodeList[childIdx];

                fragment = document.createDocumentFragment();
                copyXMLNodeToDocumentFragment(addedField, fragment);
                domNodeParent.appendChild(fragment);
            }            
        }
        else
        {
            var removed = false;
            var removedIdx;
            var xmlNodeIdx = xmlNodeListCount - 1;
            for (childIdx = domNodeListCount-1; childIdx >= 0; childIdx--)
            {
                xmlNodeChild = xmlNodeIdx < 0 ? null : xmlNodeList[xmlNodeIdx];
                domNodeChild = domNodeList[childIdx];

                var domNodeID = domNodeChild.id;
                var xmlNodeID = xmlNodeChild ? xmlNodeChild.getAttribute("id") : "";
                
                if ((xmlNodeChild==null) || (domNodeID != xmlNodeID))
                {
                    domNodeParent.removeChild(domNodeChild);
                    removed = true;
                    removedIdx=childIdx;
                }
                else
                {
                    xmlNodeIdx--;
                }
            } 
            if (removed)
            {
                for (childIdx = removedIdx; childIdx < xmlNodeListCount; childIdx++)
                {
                    xmlNodeChild = xmlNodeList[childIdx];
                    domNodeChild = domNodeList[childIdx];
                    fragment = document.createDocumentFragment();
                    copyXMLNodeToDocumentFragment(xmlNodeChild, fragment);
                    if (domNodeChild && fragment.firstChild && fragment.firstChild.style && fragment.firstChild.style.left)
                    {
                        domNodeChild.style.left = fragment.firstChild.style.left;
                    }
                }
            }
        }
    }
}

function calculateWidth(parent)
{
    var children = getChildren(parent);
    var childIdx;
    var numChildren = children.length;
    var width = 10;
    for (childIdx=0; childIdx<numChildren; childIdx++)
    {
        var child = children[childIdx];
        var calculatedWidthAttribute = child.getAttribute("calculatedwidth");
        if (calculatedWidthAttribute)
        {
            width+=parseInt(calculatedWidthAttribute);
        }
    }
    return width;    
}


function dataexplorerCreateDragContainers()
{
    var elementObj1 = getFieldGroupContainer(); 
    dataexplorerInnerCreateDragContainers(elementObj1);
};

function dataexplorerInnerCreateDragContainers(elementObj)
{
    if (elementObj)
    {
        if ((elementObj.tagName == "DIV") && (elementObj.className == "fieldgroupfields"))
        {
            CreateDragContainer(elementObj);
        }
        var children = getChildren(elementObj);
        if (children)
        {
            var numChildren = children.length;
            var childIdx;
            for (childIdx=0; childIdx < numChildren; childIdx++)
            {
                dataexplorerInnerCreateDragContainers(children[childIdx]);
            }
        }
    }
};

function dataexplorerCreateFieldResizers()
{
    var elementObj1 = getFieldGroupContainer(); 
    dataexplorerInnerCreateFieldResizers(elementObj1);
};

function dataexplorerInnerCreateFieldResizers(elementObj)
{
    if (elementObj)
    {
        if ((elementObj.tagName == "SPAN") && (elementObj.className == "fieldresize"))
//        if ((elementObj.tagName == "DIV") && (elementObj.className == "fieldresize"))
        {
            createFieldResizer(elementObj);
        }
        var children = getChildren(elementObj);
        if (children)
        {
            var numChildren = children.length;
            var childIdx;
            for (childIdx=0; childIdx < numChildren; childIdx++)
            {
                dataexplorerInnerCreateFieldResizers(children[childIdx]);
            }
        }
    }
};

function createFieldResizer(resizeSpanElement)
{
    addEventHandler(resizeSpanElement, "mousedown", fieldResizerOnMouseDown);
    addEventHandler(document, "mouseup", fieldResizerOnMouseUp);
    addEventHandler(document, "mousemove", fieldResizerOnMouseMove);
}

function fieldResizerOnMouseMove(ev)
{
    if (currentFieldResizer != null)
    {
        currentFieldResizer.onMouseMove(ev);
    }
}

function fieldResizerOnMouseDown(ev)
{
    currentFieldResizer = new fieldResizer(ev);
}

function fieldResizerOnMouseUp(ev)
{
	ev         = resolveEvent(ev);
	var target = resolveEventTarget(ev);

    if (currentFieldResizer)
    {
        currentFieldResizer.onMouseUp(ev);
        currentFieldResizer = null;
    }
}

function fieldResizer(Ev)
{

    this.initialize = function()
    {
        Ev = resolveEvent(Ev);
        this.resizeSpan = resolveEventTarget(Ev);
        /* GNPD resize span is within a nobr tag */
        this.resizeField = getParent(this.resizeSpan);
        this.resizeField = getParent(this.resizeField);
        
        
        this.initialWidth = parseInt(this.resizeField.style.width);
        this.startPosition=getMouseX(Ev);
        this.containerToResize=getParent(this.resizeField);
        this.siblingsToMove=new Array();
        
        var fields = getChildren(this.containerToResize);
        if (fields)
        {
            var thisPosition = getPosition(this.resizeField);
            var numFields = fields.length;
            var fieldIdx;
            for (fieldIdx=0; fieldIdx<numFields; fieldIdx++)
            {
                var sibling = fields[fieldIdx];
                var siblingPosition = getPosition(sibling);
                
                if (siblingPosition.x > thisPosition.x)
                {
                    this.siblingsToMove[this.siblingsToMove.length] = new fieldResizeSibling(sibling);
                }
            }
        }
    }
    
    this.onMouseMove = function(Ev)
    {
        Ev = resolveEvent(Ev);
        var newPosition = getMouseX(Ev);        
        var difference = newPosition - this.startPosition;
        var finalWidth = this.initialWidth + difference;
        if (finalWidth < 10)
        {
            finalWidth = 10;
            difference = -(this.initialWidth+finalWidth);
        }
        this.resizeField.style.width = finalWidth+"px";
        
        var numSiblingsToMove = this.siblingsToMove.length;
        var siblingIdx;
        for (siblingIdx=0; siblingIdx<numSiblingsToMove; siblingIdx++)
        {
            var siblingToMove = this.siblingsToMove[siblingIdx];
            siblingToMove.onMouseMove(difference);
        }
    }
    
    
    this.onMouseUp = function(Ev)
    {
        var Ajax = new sack("datastructureresizefield.mth"); 

        var prefix = this.resizeField.getAttribute("controlprefix");
        var uniqueFieldID = this.resizeField.getAttribute("uniquefieldid");
        var explorerStateElement  = document.getElementById(prefix+".dataexplorerstateid");
        var explorerStateID = explorerStateElement.value;
        /* Notify the server that the size of a field has changed */

//        trace("uniquenodeid = "+ uniqueFieldID);
        
        var newWidth = parseInt(this.resizeField.style.width);
        Ajax.setVar("newwidth",newWidth);  
        Ajax.setVar(prefix+".dataexplorerstateid",explorerStateID);  
        Ajax.setVar("uniquefieldid",uniqueFieldID);  
        
        Ajax.onCompletion = function DoNothing() 
        { 
        };
        
        Ajax.runAJAX();
        
        //-- resize the children of the div being resized to ensure that the reizer bar is always shown
        var children = getChildren(this.resizeField);
        var numChildren = children.length;
        var childIdx;
        var spareWidth;
        for (childIdx = 0; childIdx < numChildren; childIdx++)
        {
            var child = children[childIdx];
            if (child.className == "fieldresize") 
            {
                spareWidth = newWidth - parseInt(child.style.width) -2  ;
                break;
            }
        } 
        if (spareWidth < 0)
        {
            spareWidth = 0;
        }
        for (childIdx = 0; childIdx < numChildren; childIdx++)
        {
            var child = children[childIdx];
            if (child.className == "fieldcontent") 
            {
                if (child.style.marginLeft && child.style.marginLeft.length>0)
                {
                    spareWidth = spareWidth - parseInt(child.style.marginLeft);
                } 
                if (child.style.marginRight && child.style.marginRight.length>0)
                {
                    spareWidth = spareWidth - parseInt(child.style.marginRight) ;
                }
                if (child.style.paddingLeft && child.style.paddingLeft.length>0)
                {
                    spareWidth = spareWidth - parseInt(child.style.paddingLeft);
                } 
                if (child.style.paddingRight && child.style.paddingRight.length>0)
                {
                    spareWidth = spareWidth - parseInt(child.style.paddingRight) ;
                }
                if (spareWidth < 0)
                {
                    child.style.display = "none";
//                    trace("hiding... ");
                }
                else
                {
                    child.style.width = spareWidth+"px";
                    child.style.maxWidth = spareWidth+"px"; 
                    child.style.display = "block";
                }

                break;
            }
        } 
        resizeRightDiv();
//        var maxRight = findMaximumFieldRight();
//        var maxDepth = findMaximumFieldGroupDepth();
//        trace("max right = "+maxRight+"; maxDepth = "+maxDepth );
    }
    
    this.initialize();
}
    
function fieldResizeSibling(element)
{
    this.initialize = function()
    {
        this.fieldElement = element;
        this.initialLeft = parseInt(this.fieldElement.style.left);
    }
    
    this.onMouseMove = function(offset)
    {
        this.fieldElement.style.left = (this.initialLeft + offset) + "px";
    }
    
    this.initialize();
    
}

function dataexplorerSizeRightDivs()
{
    var rightDiv = document.getElementById("dataExplorerRightDiv");
    var resultDiv = document.getElementById("dataexplorer.dataexplorerresults");
    var dataExplorerDiv = rightDiv.parent;

    var rightDivHeight = parseInt(rightDiv.clientHeight);
    var rightDivPosition = getPosition(rightDiv);
    var resultDivPosition = getPosition(resultDiv);
    var resultDivHeight = rightDivHeight - (resultDivPosition.y - rightDivPosition.y);
    
    resultDiv.style.height = resultDivHeight + "px";
    
    
    

}


/*
** Tree Methods
*/

function dataexplorerAjaxTreeOpen(method, uniqueNodeID, xpathSelector, propertyName, prefix) 
{
    var additionalParameterNames = new Array(1);
    var additionalParameterValues = new Array(1);
    var parameterName = prefix+".dataexplorerstateid";
    var valueObject = document.getElementById(parameterName);

    additionalParameterNames[0] = parameterName;
    additionalParameterValues[0] = valueObject.value;
    ajaxTreeOpen(method, uniqueNodeID, xpathSelector, propertyName, additionalParameterNames, additionalParameterValues);
}

/*
** Do it
*/
function dataexplorerRun(prefix) 
{
    var resultDiv = document.getElementById(prefix+".dataexplorerresults"); 
    if (resultDiv)
    {
        resultDiv.innerHTML = "<P>Retrieving results</P>";
    }

    var Ajax = new sack("rundataexplorerquery.mth"); 
    
    var explorerStateElement  = document.getElementById(prefix+".dataexplorerstateid");
    var explorerStateID = explorerStateElement.value;
    
    Ajax.setVar(prefix+".dataexplorerstateid",explorerStateID);  
    setDataExplorerRunParameters(Ajax, prefix);
    
    var start = new Date().getTime();
    
    Ajax.onCompletion = function populateResults() 
    { 
        var XMLNodeList1 = this.xmlhttp.responseXML.selectNodes("/ajax/*"); 
        if (XMLNodeList1 &&  (XMLNodeList1.length > 0))
        {
            var reply = new Date().getTime();
            var elementObj1 = document.getElementById(prefix+".dataexplorerresults"); 
            
            replaceDOMChildren(XMLNodeList1, elementObj1);  
            var finished = new Date().getTime();
            
        	trace("Run finished: Time at Server = "+ ((reply-start)/1000)+" seconds; Time updating dom = "+((finished-reply)/1000)+"seconds; " );
        }
        else
        {
            if (resultDiv)
            {
                resultDiv.innerHTML = "<P>No results found</P>";
            }
        }
    };
      
	trace("about to talk to server");
    dataExplorerHideAllPropertySheets(getFieldGroupContainer());
    Ajax.runAJAX(); 
    dataexplorerSizeRightDivs();
}

function setDataExplorerRunParameters(Ajax, prefix)
{
    var fieldGroupContainer = getFieldGroupContainer();
    var inputElements = fieldGroupContainer.getElementsByTagName("input");
    var inputElement;

    var selectElements = fieldGroupContainer.getElementsByTagName("select");
    var selectElement;

    var elementIdx;
    var numElements=inputElements.length;
    
    for (elementIdx=0; elementIdx < numElements; elementIdx++)
    {
        var inputElement = inputElements[elementIdx];
        if (inputElement.type=="checkbox")
        {
            if (inputElement.checked)
            {
                Ajax.setVar(prefix+"."+inputElement.name,inputElement.value);  
            }
        }
        else
        {
            Ajax.setVar(prefix+"."+inputElement.name,inputElement.value);  
        }
    }
    
    numElements=selectElements.length;
    for (elementIdx=0; elementIdx < numElements; elementIdx++)
    {
        var selectElement = selectElements[elementIdx];
        Ajax.setVar(prefix+"."+selectElement.name,selectElement.value);  
    }
}

function hideResultGroup(id)
{
    toggleResultGroupVisibility(id, false);
}

function showResultGroup(id)
{
    toggleResultGroupVisibility(id, true);
}

function toggleResultGroupVisibility(id, show)
{
    var showImg = document.getElementById("showimg:"+id); 
    var hideImg = document.getElementById("hideimg:"+id); 
    var resultGroupDiv = document.getElementById(id); 
    if (resultGroupDiv)
    {
        if (show)
        {
            resultGroupDiv.style.display = "block";
        }
        else
        {
            resultGroupDiv.style.display = "none";
        }
    }
    if (showImg && hideImg)
    {
        if (show)
        {
            hideImg.style.display = "block";
            showImg.style.display = "none";
        }
        else
        {
            hideImg.style.display = "none";
            showImg.style.display = "block";
        }
    }
}


function highlightHeader(ev)
{
    ev = resolveEvent(ev);
    var eventTarget = resolveEventTarget(ev);
    setMouseEventBackgroundColor(eventTarget, "fieldhighlightbackgroundcolor");
}

function removeHeaderHighlight(ev)
{
    ev = resolveEvent(ev);
    var eventTarget = resolveEventTarget(ev);
    setMouseEventBackgroundColor(eventTarget, "fieldbackgroundcolor");
}


function setMouseEventBackgroundColor(eventTarget, colorAttributeName)
{
    if (eventTarget)
    {
        var headerFieldIdAttribute = eventTarget.attributes["fieldheaderid"];
        if (headerFieldIdAttribute)
        {
            var headerFieldId = headerFieldIdAttribute.value;
            var target = document.getElementById(headerFieldId);
            if (target)
            {
                var colorAttribute = target.attributes[colorAttributeName];
                target.style.backgroundColor = colorAttribute.value;
            }
        }
        else
        {
            setMouseEventBackgroundColor(eventTarget.parentNode, colorAttributeName);
        }
    }
}

function resizeRightDiv()
{
    var maxRight = findMaximumFieldRight();
    var maxDepth = findMaximumFieldGroupDepth();
//    trace("max right = "+maxRight+"; maxDepth = "+maxDepth );
    var fieldContainer = getFieldGroupContainer();
    resizeFieldGroups(fieldContainer, maxRight, maxDepth, 0);
    
    resizeContainers(fieldContainer, maxRight, maxDepth);
}

function resizeContainers(fieldContainer, maxRight, maxDepth)
{
    if (maxRight > 0)
    {
        var childIdx;
        var numChildren;
        var rightDiv = getParent(fieldContainer);
        var width = containerWidth(fieldContainer, maxRight, maxDepth);
        
        var dataExplorerDiv = getParent(rightDiv);
        var leftDiv = document.getElementById("dataExplorerLeftDiv");
        var spacerDiv = document.getElementById("dataExplorerSpacerDiv");
        var leftDivWidth = leftDiv.offsetWidth;
        var spacerDivWidth = spacerDiv.offsetWidth;

//        trace("leftDiv.offsetWidth = "+leftDiv.offsetWidth+"; spacerDiv.offsetWidth = "+spacerDiv.offsetWidth+"; width = " +width + "totalWidth = "+(5+leftDiv.offsetWidth+spacerDiv.offsetWidth +width)+"px");
        dataExplorerDiv.style.width = (5+leftDiv.offsetWidth+spacerDiv.offsetWidth +width)+"px";

        leftDiv.style.width = leftDivWidth+"px";
        spacerDiv.style.width = spacerDivWidth+"px";
        rightDiv.style.width = width+"px";

        var children = getChildren(rightDiv);
        if (children && (children.length > 0))
        {
            childIdx = 0;
            numChildren = children.length;
            for (childIdx = 0; childIdx < numChildren; childIdx++)
            {
                /* not extra text nodes */ 
                var child = children[childIdx];
                if (child.nodeType != 3)
                {
                    child.style.width = width+"px";
                }
            }
        }
    }
}

function containerWidth(container, maxRight, maxDepth)
{
    var left = getPosition(container).x;
    var width = maxRight - left;
    var margin = (1+maxDepth)*containerMarginWidth();
    return width+margin;
}

function containerMarginWidth()
{
    return 20;
}

function resizeFieldGroups(parent, maxRight, maxDepth, depth)
{
    if (maxRight > 0)
    {
        if (parent.className == "fieldgroup")
        {
            depth += 1;
            
            var left = getPosition(parent).x;
            var newWidth = maxRight - left;
            newWidth += ((1+(maxDepth-depth))*containerMarginWidth());
            parent.style.width=newWidth+"px";
        }

        var children = getChildren(parent);
        if (children && (children.length > 0))
        {
            var childIdx = 0;
            var numChildren = children.length;
            for (childIdx = 0; childIdx < numChildren; childIdx++)
            {
                var child = children[childIdx];
                resizeFieldGroups(child, maxRight, maxDepth, depth);
            }
        }
    }
}


function findMaximumFieldGroupDepth()
{
    var fieldContainer = getFieldGroupContainer();
    return innerFindMaximumFieldGroupDepth(fieldContainer, 0);
}

function innerFindMaximumFieldGroupDepth(parent, depth)
{
    var result = depth;
    if (parent.className == "fieldgroup")
    {
        result += 1;
    }

    var children = getChildren(parent);
    if (children && (children.length > 0))
    {
        var maximum = result;
        var childIdx = 0;
        var numChildren = children.length;
        for (childIdx = 0; childIdx < numChildren; childIdx++)
        {
            var child = children[childIdx];
            var nextResult = innerFindMaximumFieldGroupDepth(child, result);
            if (nextResult > maximum)
            {
                maximum = nextResult;
            }
        }
        result = maximum;
    }
    return result;
}


function findMaximumFieldRight()
{
    var fieldContainer = getFieldGroupContainer();
    return innerFindMaximumFieldRight(fieldContainer, 0);
}

function innerFindMaximumFieldRight(parent, maximum)
{
    var result = maximum;
    if (parent.className == "fieldgroupfield")
    {
        var right = getPosition(parent).x;
        right += parent.offsetWidth;
        
        if (right > result)
        {
            result = right;
        }
    }
    else
    {
        var children = getChildren(parent);
        if (children && (children.length > 0))
        {
            var childIdx = 0;
            var numChildren = children.length;
            for (childIdx = 0; childIdx < numChildren; childIdx++)
            {
                var child = children[childIdx];
                result = innerFindMaximumFieldRight(child, result);
            }
        }
    }
    return result;
}

function getFieldGroupContainer()
{
    return document.getElementById("dataexplorer.fieldgroupcontainer"); 
}

function toggleRangeFields(fieldId)
{
    var select = document.getElementById(fieldId+".term"); 
    var higherBoundSpan = document.getElementById(fieldId+".higherbound"); 
    
    if (select.value == "between")
    {
        higherBoundSpan.style.display = "inline";
    }
    else
    {
        higherBoundSpan.style.display = "none";
    }
}

function showPropertySheet(fieldId)
{
    var field =  document.getElementById(fieldId); 
    var propertySheet =  document.getElementById(fieldId+".properties"); 
    var parent = getParent(propertySheet);
    if (isHidden(propertySheet))
    {
        hidePropertySheets(parent);
        if (field && propertySheet)
        {
            propertySheet.style.display = "block";
            propertySheet.style.top = field.offsetTop+field.offsetHeight+"px";
            parent.style.height = field.offsetHeight + propertySheet.offsetHeight+10 + "px" ;
        }
    }
    else
    {
        if (field && propertySheet)
        {
            showFilterIcon(propertySheet, fieldId);
            showSortIcon(propertySheet, fieldId);
            hideElement(propertySheet);
            parent.style.height = field.offsetHeight + 10 + "px" ;
        }
    }
}

function showSortIcon(propertySheet, fieldId)
{
    var significantSort = isSortSignificant(propertySheet, fieldId);
    var sortImageContainer = document.getElementById(fieldId+".sortimagecontainer");
    if (sortImageContainer)
    {
        if (significantSort)
        {
            setSortImageAlt(propertySheet, fieldId); 
            sortImageContainer.style.display="inline";
        }
        else
        {
            sortImageContainer.style.display="none";
        }
    }
}

function setSortImageAlt(propertySheet, fieldId)
{
    var altString = "Sorted ";
    /* text filter */
    var sortImage = document.getElementById(fieldId+".sortimage");
    var sortSelect = document.getElementById(fieldId+".sort");
    var sortLevel = document.getElementById(fieldId+".sortlevel");
    if (sortImage && sortSelect && (sortSelect.value != "none"))
    {
        switch (sortSelect.value.toLowerCase())
        {
            case "ascending":   {   altString = "ascending: ";              } break;
            case "descending":  {   altString = "descending: ";             } break;
            default:            {   altString = sortSelect.value + ": ";    } break;
        }
        altString += "Level "+sortLevel.value;

        sortImage.alt = altString;        

    }
}

function isSortSignificant(propertySheet, fieldId)
{
    var significant = false;
    /* text filter */
    var sortSelect = document.getElementById(fieldId+".sort");
    if (sortSelect && (sortSelect.value != "none"))
    {
        significant = true;
    }
    return significant;
}



function showFilterIcon(propertySheet, fieldId)
{
    var significantFilter = isFilterSignificant(propertySheet, fieldId);
    var filterImageContainer = document.getElementById(fieldId+".filterimagecontainer");
    if (filterImageContainer)
    {
        if (significantFilter)
        {
            setFilterImageAlt(propertySheet, fieldId); 
            filterImageContainer.style.display="inline";
        }
        else
        {
            filterImageContainer.style.display="none";
        }
    }
}

function setFilterImageAlt(propertySheet, fieldId)
{
    var altString = "";
    /* text filter */
    var filterImage = document.getElementById(fieldId+".filterimage");
    var filterValue = document.getElementById(fieldId+".filtervalue");
    var higherFilterValue = document.getElementById(fieldId+".filtervalue1");
    var filterTerm = document.getElementById(fieldId+".term");
    if (filterTerm && filterValue && (filterValue.value.length > 0))
    {
        switch (filterTerm.value.toLowerCase())
        {
            case "equal":       {   altString = "Equals: ";         } break;
            case "contains":    {   altString = "Contains: ";       } break;
            case "startswith":  {   altString = "Starts With: ";    } break;
            case "gt":          {   altString = "Greater Than: ";   } break;
            case "lt":          {   altString = "Less Than: ";      } break;
            case "between":     {   altString = "Between: ";        } break;
            default:            {   altString = filterTerm + ": ";  } break;
        }
//        var filterTerm = document.getElementById(fieldId+".term");
        altString += filterValue.value;
        if (higherFilterValue && (higherFilterValue.value.length>0))
        {
            altString += " and ";
            altString += higherFilterValue.value;
        }

        filterImage.alt = altString;        
    }
}

function isFilterSignificant(propertySheet, fieldId)
{
    var significant = false;
    /* text filter */
    var filterValue = document.getElementById(fieldId+".filtervalue");
    if (filterValue && (filterValue.value.length > 0))
    {
        significant = true;
    }
    else
    {
        var inputElements = propertySheet.getElementsByTagName("input");
        var inputElement;

        var elementIdx;
        var numElements=inputElements.length;
        
        for (elementIdx=0; elementIdx < numElements; elementIdx++)
        {
            var inputElement = inputElements[elementIdx];
            if (inputElement.type=="checkbox")
            {
                if (inputElement.checked)
                {
                    significant=true;
                    break;
                }
            }
        }
    }
    return significant;
}

function dataExplorerHideAllPropertySheets(element)
{
    var children = getChildren( element );
    var numChildren = children.length;
    var childIdx;
    for (childIdx = 0; childIdx<numChildren; childIdx++)
    {
        var child = children[childIdx];
        if (child.className == "fieldgroupfields")
        {
            hidePropertySheets(child);
        }
        else
        {
            dataExplorerHideAllPropertySheets(child);
        }
    }
}

function hidePropertySheets(parent)
{
    var children = getChildren(parent);
    var childIdx;
    var numChildren = children.length;
    var containerResized = false;
    for (childIdx = 0; childIdx < numChildren; childIdx++)
    {
        var child = children[childIdx];
        if (child.className == "dataexplorerpropertysheet")
        {
            var fieldId = getFieldIdFromPropertySheet(child); 
            showFilterIcon(child, fieldId);
            showSortIcon(child, fieldId);
            hideElement(child);
            if (!containerResized)
            {
                var field = document.getElementById(fieldId);
                if (field)
                {
                    parent.style.height = field.offsetHeight + 10 + "px" ;
                }
                containerResized=true;
            }
        }
    }
}

function getFieldIdFromPropertySheet(propertySheet)
{
    var propertySheetId = propertySheet.id;
    var prefix = "fieldgroupfield";
    var fieldId = propertySheetId.substr(0, prefix.length+36);
    return fieldId;
}

function hideElement(element)
{
    element.style.display = "none";
}

function isHidden(element)
{
    return element.style.display == "none";
}
