/* package all control values on the specified form
   into the given node */
function saveFormControls( controlsNode,formID )
{
  var saveForm = document.getElementById( formID );
  var Control;

  for ( var Index = 0; Index < saveForm.length; Index++ )
  {
    Control = saveForm[ Index ];

    if ( Control.id.length > 0 )
    {
      saveControl( controlsNode,Control );
    }
  }
}

/* save a single control to XML document.
   returns true if the control was found otherwise false if added */
function saveControl( controlsNode,control )
{
  var controlNode;
  var validControl = true;
    
  /* find the node for this control TODO: use an XPATH */
  for ( var Index = 0;Index < controlsNode.childNodes.length; Index++ )
  {
    controlNode = controlsNode.childNodes[ Index ];

    if ( controlNode.getAttribute( "id" ) == control.id )
    {
      break;
    }
    controlNode = null;
  }

  /* node not found, add a new one */
  if ( controlNode == null )
  {
    controlNode = controlsNode.ownerDocument.createElement( "ctrl" );
    controlNode.setAttribute( "id",control.id );
  }

  /* set value */
  switch( control.type )
  {
    case "text" : controlNode.text = control.value; break;
    case "textarea" : controlNode.text = control.value; break;
    case "hidden" : 
      if ( control.name.length > 2 )
      {
        /** Exclude .NET hidden fields */
        if ( control.name.substr(0,2) != "__" )
        {
          controlNode.text = control.value;
        }
      }
      else
      {
        controlNode.text = control.value;
      }
      break;
    case "select-one" : 
      controlNode.text = control.options[ control.selectedIndex ].value;
      break;

    case "select-multiple" : controlNode.text = getSelectedIndex( control ); break;
    case "checkbox" :
      if ( control.checked )
      {
        controlNode.text = "true";
      }
      else
      {
        controlNode.text = "false";
      }

      break;
    default : 
        validControl = false;
        break;
  }
  
  if ( validControl )
  {
      controlsNode.appendChild( controlNode );
  }
}

/* returns the indices of all selected options in the control */
function getSelectedIndex( control )
{
  var selectStr = "";
  var optionCount = control.options.length;

  for ( var optionIdx=0; optionIdx < optionCount;optionIdx++ )
  {
    if ( control.options[ optionIdx ].selected )
    {
      if ( selectStr.length > 0 )
      {
        selectStr += ",";
      }

      selectStr += optionIdx.toString();
    }
  }
  return selectStr;
}


/* checks a value to see if it is a number
 Returns: 0 - Not a number, 1 - valid, 2 - Out of range
*/
function checkNumber( aValue,IsInteger,HasMax,MaxValue )
{
  var ValidCharSet = ".,0123456789";
  var DecimalChar  = ".";
  var ThousandChar = ",";
  var CurrentChar;
  var DecimalIndex = -1;
  var DecimalCount = 0;
  var FinalValue   = "";
  var ReturnValue  = 0;

  if ( aValue.length < 1 )
  {
    return 0;
  }

  for ( var Index = 0; Index < aValue.length; Index ++ )
  {
    CurrentChar = "" + aValue.substring( Index,Index+1 );

    if ( ValidCharSet.indexOf( CurrentChar ) == "-1" )
    {
      return 0;
    }

    if ( CurrentChar==DecimalChar )
    {
      DecimalCount += 1;
      if ( DecimalCount > 1 ) return 0;
      DecimalIndex = Index;
    }

    if ( ( CurrentChar==ThousandChar ) && ( DecimalIndex > -1 ) )
    {
      if ( DecimalIndex < Index ) return 0;
    }

    if ( CurrentChar != "," )
    {
      FinalValue += CurrentChar;
    }
  }

  ReturnValue=1;

  if ( HasMax )
  {
    if ( parseFloat( FinalValue ) > MaxValue )
    {
      ReturnValue = 2;
      aValue = MaxValue;
    }
  }

  if ( ( IsInteger ) && ( DecimalCount > 0 ) )
  {
    FinalValue = FinalValue.substring( 1,DecimalIndex-1 );
  }

  return ReturnValue;
}


/* Set the style of the text box subject to the state
   IsInteger is TRUE by default
*/
function onchangeNumericTextBox( control,IsInteger )
{
  if ( IsInteger == null )
  {
    IsInteger = true;
  }
  
  var TextValue = control.value;
  var State = checkNumber( TextValue,IsInteger,false );
  var PrevClass = control.getAttribute( "pclassname" );
  var ReturnVal = true;

  if ( State > 0 )
  {
    ReturnVal = true;

    if ( ( PrevClass != null ) && ( PrevClass!= "tbinterr" ) )
    {
      control.className = PrevClass;
    }
    else
    {
      control.className = "tbint";
    }

    /* remove the error message */
    var errControl = document.getElementById( "err" + control.id );

    if ( errControl != null )
    {
      control.parentElement.removeChild( errControl );
    }
  }
  else
  {
    if ( control.className != "tbint" )
    {
      control.setAttribute( "pclassname",control.className );
    }

    control.className = "tbinterr";
    /* add the error message */
    control.outerHTML += "<span id=err" + control.id + " class=\"errnumber\">Number required</span>";
  }

  return ReturnVal;
}


/* change visibility of object */
function ObjectVisibility( objid,visible )
{
  var obj = document.getElementById( objid );

  if ( obj != null )
  {
    if ( visible != null )
    {
      if ( visible )
      {
        obj.style.display = "block";
      }
      else
      {
       obj.style.display = "none";
      }

      return visible;
    }
    else
    {
      if ( obj.style.display != "block" )
	  {
	    obj.style.display = "block";

        return true;
	  }
	  else
	  {
	    obj.style.display = "none";

        return false;
	  }
    }
  }
}


/* enable or disable a control using their ID  and apply the appropriate style class */
function EnableControlByID( objid,enabled,enablecss,disablecss )
{
  var obj = document.getElementById( objid );

  if ( obj != null )
  {
    obj.disabled = !enabled;

    if ( ( !obj.disabled ) && ( enablecss != null ) )
    {
      obj.className = enablecss;
    }
    else
    if ( ( obj.disabled ) && ( disablecss != null ) )
    {
      obj.className = disablecss;
    }

  }
}


/*  sets the location for the current window */
function setLocation( locationURL )
{  
  if ( ( locationURL != null ) & ( locationURL.length > 0 ) )
  {
    document.location.href = locationURL;
  }
}


/** Standard search
*/
function onSearch( areaID,viewID )
{
    var dlgParent;
    dlgParent = null;
    
    if ( opener != undefined )
    {
        dlgParent = opener;
    }
    else
    if ( window.dialogArguments != undefined )
    {
        dlgParent = window.dialogArguments;
    }
    
    if ( dlgParent != null )
    {
        if ( dlgParent.openSearch != undefined )
        {
            dlgParent.openSearch(areaID,viewID);        
        }        
    }    
}


/** Calls a set of standard parent update routines when the dialog is closed.
*/
function onCloseDialog()
{
    var dlgParent;
    dlgParent = null;
    
    if ( opener != undefined )
    {
        dlgParent = opener;
    }
    else
    if ( window.dialogArguments != undefined )
    {
        dlgParent = window.dialogArguments;
    }
    
    if ( dlgParent != null )
    {
        if ( dlgParent.Navigate != undefined )
        {
            dlgParent.Navigate(1);        
        }
        else
        if ( dlgParent.childClosing != undefined )
        {
            dlgParent.childClosing(1);        
        }
    }
}


/** Open page in new window 
@param pageURL The URL of the page to open.
@param pageTitle The title of the dialog.
@param pWidth The width of the dialog in px.
@param pHeight  The width of the dialog in px.
@param showScrollBars Set to true to show scrollbars.
@param showMenu Set to true to show the menu bar.
@param resizeWindow Set to true to allow the window to be resized.
@param windowState Set to null or 0 for window.open functionality, 1 for modeless dialog and 2 for modal dialog.
*/
function OpenPage( pageURL,pageTitle,pWidth,pHeight,showScrollBars,showMenu,resizeWindow,windowState )
{
  var newURL = pageURL;
  var scrollYesNo = "no";
  var menuYesNo = "no";
  var sizeYesNo = "no";
  var isIE7 = /*@cc_on!@*/false && ( parseInt( navigator.userAgent.toLowerCase().match( /msie (\d+)/ )[1] ) >= 7 ); 
      
  if ( windowState == null )
  {
    //0 - Use window.open for legacy
    //1 - Modeless
    //2 - Modal
    windowState=0;  
  }
    
  if ( ( showScrollBars != null ) && ( showScrollBars ) )
  {
    scrollYesNo = "yes";
  }

  if ( ( showMenu != null ) && ( showMenu ) )
  {
    menuYesNo = "yes";
  }

  if ( ( resizeWindow != null ) && ( resizeWindow ) )
  {
    sizeYesNo = "yes";
  }
  
  if ( ( isIE7 ) & ( showMenu != "yes" ) & ( windowState != 0 ) )
  {
    switch ( windowState )
    {
        case 1 :
            showModelessDialog( newURL,window,"dialogWidth:" + pWidth.toString() + "px;dialogHeight:" + pHeight.toString() + "px;status:no;resizable:" + resizeWindow + ";scroll:" + scrollYesNo + ";" );   
            break;
        
        case 2 :
            showModalDialog( newURL,window,"dialogWidth:" + pWidth.toString() + "px;dialogHeight:" + pHeight.toString() + "px;status:no;resizable:" + resizeWindow + ";scroll:" + scrollYesNo + ";" );   
            break;
            
        default :
            alert( "The window state \"" + windowState.toString() + "\" is not supported. Use 0 (open), 1 (modeless), or 2 (modal)");
            break;    
    }    
  }
  else
  {
    window.open(newURL,pageTitle,"top=20,left=20,status=no,scrollbars=" + scrollYesNo + ",menubar=" + menuYesNo + ",width=" + pWidth + ",height=" + pHeight + ",resizable=" + sizeYesNo ); 
  }     
  
  return false;
}


/* open page in new window */
function OpenPageFromLink( linkControl,wndWidth,wndHeight,showScrollBars,showMenu )
{
  if ( linkControl != null )
  {
    var urlString = linkControl.href;
    var scrollYesNo = "no";
    var menuYesNo = "no";
    
    if ( ( showScrollBars != null ) && ( showScrollBars ) )
    {
      scrollYesNo = "yes";
    }

    if ( ( showMenu != null ) && ( showMenu ) )
    {
      menuYesNo = "yes";
    }

    window.open( urlString,"","status=no,scrollbars=" + scrollYesNo + ",menubar=" + menuYesNo + ",width=" +
                 wndWidth.toString() + ",height=" + wndHeight.toString() );
  }
  return false;
}



/* sets the browser window size */
function setWindowSize( Width,Height )
{
  window.resizeTo( Width,Height );
}


/* returns true if the array contains the value.
   TODO: is there a standard call for this? */
function HasValue( anArray,searchValue )
{
  var itemCount = anArray.length;

  for ( var index=0;index < itemCount;index++ )
  {
        if ( anArray[index].value==searchValue )
        {
            return true;
        }
  }

  return false;
}


/* refreshes the page without any specific event */
function RefreshPage( ControlID )
{
  if ( ControlID == null )
    ControlID = "";

  //TODO: cannot rely on this method staying consistent
  __doPostBack(ControlID,"");
}



/* Yes/No confirm dialog for deleting items */
function confirmDelete( promptText )
{
  if( promptText == null )
    promptText = "Are you sure you wish to delete this item?";

  var cresult = confirm( promptText );

  return cresult;
}


/* provides simple handling of <message/> documents */
function handleMessage( messageXML )
{                     
  var mStatus = 0;

  if ( messageXML != null )
  {
    if ( messageXML.documentElement != null )
    {
      mStatus = parseInt( messageXML.documentElement.getAttribute( "status" ) );
      var mType = parseInt( messageXML.documentElement.getAttribute( "type" ) );
      var contentText = messageXML.documentElement.childNodes[0].text;

      if ( contentText.length > 0 )
      {  
        switch( mType )
        {
          case 1 : alert( contentText ); break;
        }
      }
    }
  }

  return mStatus;
}



/* load all of the control data from the XML node.
   XML is requested from the parent to avoid problems with page loading etc. */
function loadControls( senderContentChange,controlsXML,clearState,stateHandler )
{
  var hasDifferences = false;
  var stateClear = true;

  if ( clearState != null )
  {
    stateClear = clearState;
  }

  if ( controlsXML != null )
  {
    if ( controlsXML.childNodes.length > 0 )
    {
      var ctrlsNode = controlsXML.childNodes[ 0 ];
      var ctrlNode;
      var docCTRL;
      var ctrlDifferences = false;

      if ( ctrlsNode.childNodes.length > 0 )
      {                         
        senderContentChange( null );
      }

      var nodeCount = ctrlsNode.childNodes.length; 

      for ( var Index = nodeCount-1; Index >-1 ;Index-- )
      {
        ctrlNode = ctrlsNode.childNodes( Index );
        docCTRL = document.getElementById( ctrlNode.getAttribute( "id" ) );

        if ( docCTRL != null )
        {
          if ( stateClear )
          {
            /* check to see if the default control values are up to date */
            switch( docCTRL.type )
            {
              case "text" :
                ctrlDifferences = !compareValues( docCTRL.value,ctrlNode.text ); break;

              case "textarea" : ctrlDifferences = docCTRL.value != ctrlNode.text; break;
              case "hidden" : ctrlDifferences = docCTRL.value != ctrlNode.text; break;
              case "select-one" :
                if ( docCTRL.selectedIndex > -1 )
                {
                  ctrlDifferences = docCTRL.options[ docCTRL.selectedIndex ].value != ctrlNode.text;
                }
              break;

              case "select-multiple" :
                var selectStr = getSelectedIndex( docCTRL );
                ctrlDifferences = ctrlNode.text != selectStr;
              break;

              case "checkbox" : ctrlDifferences = docCTRL.checked != ( ctrlNode.text == "true" ); break;
            }

            if ( clearState != null )
            {
              ctrlDifferences = false;
            }
          }
          else
          {
            ctrlDifferences = true;
          }

          /* remove child nodes that contain no differences */
          if ( !ctrlDifferences )
          {
            ctrlsNode.removeChild( ctrlNode );
          }
          else
          /* set the control value from XML state */
          {
            hasDifferences = true;

            switch( docCTRL.type )
            {
              case "text" : docCTRL.value = ctrlNode.text; break;
              case "textarea" : docCTRL.value = ctrlNode.text; break;
              case "hidden" : docCTRL.value = ctrlNode.text; break;
              case "select-one" :
                setIndexByValue( docCTRL,ctrlNode.text );
                break;

              case "select-multiple" :
                var selectArray = ctrlNode.text.split( "," );
                var optionIdx;
                var optionCount = docCTRL.options.length;
                var arrayCount = selectArray.length;

                for ( var arrayIdx = 0; arrayIdx < optionCount; arrayIdx++ )
                {
                  docCTRL.options[ arrayIdx ].selected = false;
                }

                for ( var arrayIdx = 0; arrayIdx < arrayCount; arrayIdx++ )
                {
                  optionIdx = parseInt( selectArray[ arrayIdx ] );

                  if ( optionIdx < optionCount )
                  {
                    docCTRL.options[ optionIdx ].selected = true;
                  }
                }
              break;
              case "checkbox" : docCTRL.checked = ctrlNode.text == "true"; break;
            }

            setControlHighlight( docCTRL );
          }
        }
      }
      stateHandler.onchangeContent();
    }
    else
    {
      var ctrlsNode = controlsXML.ownerDocument.createElement( "ctrls" );
      controlsXML.appendChild( ctrlsNode );
    }
  }
}


/* highlight a control */
function setControlHighlight( control )
{
  if ( control != null )
  {
    control.style.background = "#ccffcc"
  }
  else
  {
    control.style.background = "null";
  }
}



/* compares two values to see if they are equivalent
  TODO: replace with standard routine
*/
function compareValues( value1,value2 )
{
  var dv1 = parseFloat( value1 );
  var dv2 = parseFloat( value2 );

  if ( ( dv1.toString != "NaN" ) & ( dv2.toString() != "NaN" ) )
  {
    return dv1==dv2;
  }
  else
  {
    return value1.toString() == value2.toString();
  }
}


/* sets list index by value */
function setIndexByValue( control,value )
{    
  var itemCount;
  itemCount = control.options.length;
   
  for ( var idx = 0;idx < itemCount;idx++ )
  {      
    var opt = control.options[idx];

    if ( opt.value == value )
    {
      control.selectedIndex = idx;
      break;
    }
  }
}


/* closes the window */
function closeWindow()
{
  window.close();
  return false;
}


/** Sets the inner text for an element subject to the support
given by the client

@param element The element to set
@param innerText The text to set in the element

*/
function setInnerText( element,innerText )
{
  if ( navigator.appName == "Microsoft Internet Explorer" )
  {
    element.innerText = innerText;
  }
  else
  if ( element.textContent != undefined )
  {
    element.textContent = innerText;
  }
  else
  {
    alert( "Unable to set inner text for element in setInnerText()" );
  }
}


/** returns an XML document depending on what's available for the
   client browser

   @param documentString The string representation of the XML to be loaded into the document object.
   \return The XML document.
*/
function getXMLDocument( documentString )
{
   if ( documentString == undefined )
   {
     documentString = "";
   }

   var xmlDoc;

   if ( window.ActiveXObject )
   {
      xmlDoc = new ActiveXObject("Microsoft.XMLDOM");

      if ( documentString.length > 0 )
      {
        xmlDoc.loadXML( documentString );
      }
   }
   // code for Mozilla, Firefox, Opera, etc.
   else
   if ( document.implementation && document.implementation.createDocument )
   {
     if ( documentString.length > 0 )
     {
       var parser = new DOMParser();
       xmlDoc = parser.parseFromString( documentString,"text/xml");
     }
     else
     {
       xmlDoc = document.implementation.createDocument( "","",null );
     }
   }
   else
   {
     alert("Unable to create XML document in getXMLDocument()");
   }

   return xmlDoc;
}




/* returns an XML HTTP Request depending on what's available */
function getXMLHTTPRequest()
{
  var newRequest = null;

  try
  {
    newRequest = new ActiveXObject("Microsoft.XMLHTTP");
  }
  catch (e)
  {
  }

  if ( newRequest == null )
  {
    newRequest = new XMLHttpRequest();
  }

  if ( newRequest == null )
  {
    alert( "Failed to create XML HTTP Request" );
  }

  return newRequest;
}


/* returns an XML HTTP Request depending on what's available */
function getXMLParentNode( childNode )
{
  var pNode = null;

  if ( childNode != null )
  {
    if ( childNode.parentElement != undefined )
    {
      pNode = childNode.parentElement;
    }
    else
    if ( childNode.parentNode != undefined )
    {
      pNode = childNode.parentNode;
    }
    else
    {
      alert( "Unable to get parent node of childNode" );
    }
  }

  return pNode;
}


/* returns the index of the value in the list */
function indexOfValue( listControl,value )
{
  var valueIndex = -1;
  var checkValue = value.toLowerCase();
  var optionCount = listControl.options.length;

  for( var index=0;index < optionCount; index++ )
  {
    if ( listControl.options[ index ].value.toLowerCase() == checkValue )
    {
      valueIndex = index;
      break;
    }
  }

  return valueIndex;
}

