//////////////////////////////////////////////////////////////////////////////////////
//  File:            page.js
//  Description:     This file conatains the page and row classes. This Page class is
//                   used to create dynamic pages. It contain methods to create various
//                   inputs with automatic data validation. The Row class contains
//                   methods for creating the rows on the page.
//  Original Author: Jonathan J. Smith (jonathan.smith@polycom.com)
//////////////////////////////////////////////////////////////////////////////////////

var kDefaultFormName = "settings"
var kDefalutFormMethod = "post"
var kDefalutEncType = ""
var kDefalutFormAccept = ""
var kAttributeSeperator = "?"
var kAttValueSeperator = "|"
var kDependentRows = "dependentRows"
var textNodeCount = 0 // We use this to give each text node a unique id

// This is the page object. There is always one and only one
// page so it is created here. There are other ways to create
// a singleton in JavaScript but they have there own disadvantages.
page = new Page ()

// The Page class
function Page ()
{ 
  this.pageName = null
  this.formName = null
  this.groupName = null
  this.action = ""
  this.style = "configData"
  this.currentRow = 0
  this.tabed = 0
  this.onhide = null
  this.onshow = null
  this.pageTableBody = null
  this.dataTableBody = null
  this.bootOnAnyChanges = false
  this.bootOnSomeChanges = false
  this.rows = new Array ()
  this.useColumns = false
  this.dataTableCount = 0
  this.currentIndent = 0
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        ForceBootOnAnyChange
//  Description: Set the flag that this page will cause a reboot on any change.
////////////////////////////////////////////////////////////////////////////////

Page.prototype.ForceBootOnAnyChange = function ()
{
  this.bootOnAnyChanges = true
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        IsRebootNeeded
//  Description: Check to see if any thing changed that would cause a reboot
////////////////////////////////////////////////////////////////////////////////

var kInputTypes = new Array ("input", "select", "img")

Page.prototype.IsRebootNeeded = function ()
{
  if (isOOB) return false
  // alert ("IsRebootNeeded () : " + this.bootOnAnyChanges + "; " +this.bootOnSomeChanges)
 
  if (this.bootOnAnyChanges || this.bootOnSomeChanges)
  {
    var inputType
    
    for (inputType in kInputTypes)
    {
      if (CheckListForReboot (document.getElementsByTagName(kInputTypes[inputType])))
        return true
    }
  }
  return false
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        OnClickBackNext
//  Description: if we are OOB then and we are not on the last screen we need to
//               submit when clicking back or next
////////////////////////////////////////////////////////////////////////////////

Page.prototype.OnClickBackNext = function (nextPage, onSubmit, form)
{
  var OOBObj = document.getElementById ("outofbox")
  
  if (isOOB && !OOBObj || (OOBObj && OOBObj.value != "False"))
  {
    document.getElementById ("htmfile").value = nextPage;
    this.CheckAndSubmitForm (onSubmit, form);
  }
  else
  {
    if (document.frames.contentFrame)
    {
       document.getElementById ("contentFrame").contentWindow.location.replace (nextPage);
    }
    else // We are viewing the page directly
    {
       document.location.replace (nextPage);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        CheckAndSubmitForm
//  Description: Verify that all of the page fields contain valid data
//               and submit the form.
////////////////////////////////////////////////////////////////////////////////

Page.prototype.CheckAndSubmitForm = function (onSubmit, form)
{
  // If the page contains a content frame then we are viewing the inside the
  // frame on the main page and we need to call the submit function from
  // within that frame.
  // alert ("page.CheckAndSubmitForm")
  var cFrame = document.getElementById ("contentFrame")
  if (cFrame) 
    return cFrame.contentWindow.page.CheckAndSubmitForm (onSubmit, form)

  if (!form) form = this.formName
  if (CheckForm (form))
  {
    // If the system needs to be rebooted prompt the user to make sure
    // they want to submit the page
    // alert ("onSubmit = \"" + onSubmit + "\"");
    if (((onSubmit == null || onSubmit == "" ) ? true : eval (onSubmit)))
    {
      if (this.IsRebootNeeded ()) 
      {
        if (confirm (APPLICATION_MUST_BE_RESTARTED))
        {
          // If we need to reboot and the page has an action than that
          // action will have to force the reboot.
          if (this.GetAction (form) == "") this.SetAction (rebootAction, form);
          document.getElementById ("htmfile").value = "a_rebootmeter.htm"
        }
        else
        {
           return false;
        }
      }
      //alert ("Submit the form and reload "+GetHTMFile()+" action = "+page.GetAction ())
      this.Submit (form)
      return true;  // For completeness
    }
  }
  return false;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddBodyEnd
//  Description: Add the back, next and update buttons and a function to be
//               executed on submitting of the page.
//
//  backPage     = The url to go to when the back button is clicked.
//  nextPage     = The url to go to when the next button is clicked.
//  showUpdate   = Indecates wether or not we want to show the update button.
//                 (default = true)
//  backPage     = The url to go to when the back button is clicked.
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddBodyEnd = function (backPage, nextPage, showUpdate, onSubmit)
{
  var newRow
  
  if (this.bootOnAnyChanges) this.AddFootnoteText (CHANGES_WILL_REBOOT)
  if (this.bootOnSomeChanges) this.AddFootnoteText (CHANGES_RESTART_WEB)

  if (document.getElementById ("htmfile") == null)
    this.AddHiddenInput ("htmfile", ((nextPage) ? nextPage :
      GetCurrentPageName ()))
  
  // Register for changes to dependent objects
  for (rowIndex in this.rows)
  {
    var newRow = this.rows[rowIndex]
    this.RegisterForChanges (newRow.dependentObjects, newRow.rowNumber)
  }
  
  // Create all of the rows
  for (rowIndex in this.rows)
  {
    var newRow = this.rows[rowIndex]
    var newRowPtr = newRow.CreateRow ()

    if (newRowPtr != null)
    {
      newRow.dataTable.appendChild (newRowPtr)
      if (newRow.oncreationof != null && newRow.oncreationof != "") eval (newRow.oncreationof)
    }
  }
  
  this.AddUpdateNextButtons (backPage, nextPage, showUpdate, onSubmit)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddBodyEnd
//  Description: Set the page, form and group name. Create the main form
//               and table.
//
//  pageName     = The name of the page.
//  formName     = The name of the form.
//  groupName    = The name of the group. This should match the embedded group.
//  action       = The action to take on submit. In OOB mode this defaluts to
//                 "a_gotonext.cgi"
//  method       = The form submit method (default = "post").
//  encType      = The form encryption type.
//  accept       = The form accept value
//  style        = The CSS style for the main table (default = "configData")
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddBodyStart = function (pageName, formName, groupName, action,
  method, encType, accept, style)
{
  this.pageName = pageName
  this.groupName = groupName
  if (style) this.style = style

  this.dBody = document.body
  this.endOfPage = this.dBody.appendChild (
    CreateElement ('<table id="configData" class="'+this.style+'">'))
  this.endOfPage = this.endOfPage.appendChild (CreateElement ('<tbody>'))
  this.pageTableBody = this.endOfPage
  // If we are loading this page inside the menus the page title will row
  // will already be there.
  if (!parent.document.getElementById ("pageTitle"))
  {
    var newElement = this.endOfPage.appendChild (CreateElement ('<tr id="headerRow">'))
    newElement = newElement.appendChild (CreateElement ('<td>'))
    newElement.appendChild (this.CreateHeaderTable ())
  }
  
  this.AddPageLabel (this.pageName)
  
  this.pageTableBody = this.pageTableBody.appendChild (CreateElement ('<tr>'))
  this.pageTableBody = this.pageTableBody.appendChild (CreateElement ('<td>'))
  
  if (formName) this.AddForm (formName, method, action, encType, accept)
  this.AddDataTableStart ()                    
  this.AddGroup ()
  if (this.bootOnAnyChanges) this.AddFootnoteText (CHANGES_WILL_REBOOT)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddCheckBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddCheckBox = function (name, value, onChange,
  forceNavUpdate, rebootOnChange, isReadOnly, condition)
{

  var checkBox
  var checkBoxHelper
  var checked = value == "True"
  var newElement = document.createDocumentFragment()
  var checkBoxName = name + "checkbox"
  onChange = (!onChange) ? "" : onChange + ";"

  if (isReadOnly == null) isReadOnly = false
  onClick = 'ClickCheckBoxImage(this, true);'
  onChange += 'UpdateDependentRows (document.getElementById(\''+name+'\'));'
  if (forceNavUpdate) onClick += 'UpdateNavReloadCB(this);'
  // Create the checkbox Image
  checkBox = CreateElement ('<img onclick="'+onClick+'" '+
//    'src="'+("checkbox" + value + ".png")+'" ' +
//    'disabled="'+isReadOnly+'"' +
//    'helper="'+name+'"' +
    'name="'+checkBoxName+'" id="'+checkBoxName+'">')
  checkBox.onchange = Function ("onchange"+name, onChange)
  checkBox.setAttribute ("disabled", isReadOnly)
  checkBox.setAttribute ("helper", name)
  SetImageValue (checkBox, checked)
  checkBox.src = GetCheckBoxImageName (checkBox)
  this.SetCommonAttributes (checkBox, rebootOnChange, condition);
  newElement.appendChild (checkBox);
  // Create the helper
  checkBoxHelper = CreateElement ('<input type="hidden" id="'+name+
    '" name="'+name+'" value="'+value+'">');
  this.SetCommonAttributes (checkBoxHelper, rebootOnChange, condition);
  newElement.appendChild (checkBoxHelper);
  return newElement;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddDataTableStart
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddDataTableStart = function (useColumns)
{
  this.dataTableCount++
  this.useColumns = (useColumns) ? useColumns : false
  this.dataTableBody = this.pageTableBody.appendChild (CreateElement
    ('<table class="dataTable" id="dataTable'+this.dataTableCount+
    '" border="0" cellpadding="0" cellspacing="2">'))
  this.dataTableBody = this.dataTableBody.appendChild (
    CreateElement('<tbody id="dataTableBody'+this.dataTableCount+'">'))
  
  return "dataTableBody"+this.dataTableCount
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddDoubleByteEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddDoubleByteEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, 'ValidateDoubleByte',
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddEditBox = function (name, value, length, size, dataValidation, 
  onChange, isRequired, requiredText, rebootOnChange, condition, parameters)
{
  return this.CreateInput ("text", name, value, length, size, dataValidation,
  onChange, isRequired, requiredText, rebootOnChange, condition, parameters)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddEmailEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddEmailEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  //var validateFunc = 'tmt_RegExpValidator(\''+name+
    //'\',\'%5E%5B%5Cw%5C.=-%5D%2B@%5B%5Cw%5C.-%5D%2B%5C.%5Ba-z%5D%7B2,3%7D$\',INVALID_EMAIL,\'\',\'\');'
  return this.AddEditBox (name, value, length, size, "EmailOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddFootnoteText
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddFootnoteText = function (textID, rowId)
{
  if (!rowId) rowId = "footnoterow"
  
  this.AddRow ('name='+rowId, 'style=footnote', 'columns=2',
    page.AddTextNode (textID))
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        StartSection
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.StartSection = function (rowId, label)
{
  this.AddRow ('name='+rowId, 'style=label',
   'columns=2', 'tabed='+this.currentIndent++,
    page.AddTextNode (label))
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        StartNewSection
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.EndSection = function ()
{
  this.currentIndent--
}
////////////////////////////////////////////////////////////////////////////////
//  Name:        AddWebLanguageSelect
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddWebLanguageSelect = function  ()
{
  return this.AddRadioList ("web_language", webLanguags, GetLanguage (),
    "MM_OnLanguageChange(this.value);")
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddForm
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddForm = function (formName, method, action, encType, accept)
{
  var newRow
  var newForm
  
  this.formName = formName
  this.action = (isOOB && action == null) ? "a_gotonext.cgi" : 
   (action) ? action : ""
  method = (method) ? method : kDefalutFormMethod
  encType = (encType) ? ' enctype="'+encType+'"' : kDefalutEncType
  accept = (accept) ? ' accept="'+accept+'"' : kDefalutFormAccept

  this.pageTableBody = this.pageTableBody.appendChild (CreateElement
    ('<form name="'+this.formName+'" method="'+method+
      '" action="'+this.action+'"'+encType+accept+'>'))
  //this.pageTableBody = this.endOfPage
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddGroup
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddGroup = function ()
{
  if (this.groupName != null && this.groupName != "")
    this.AddHiddenInput ("_groupname", this.groupName)
}


////////////////////////////////////////////////////////////////////////////////
//  Name:        AddImage
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddImage = function (name, src, args, onClick)
{
  return CreateElement ('<img onclick="'+onClick+'" src="'+src+'" name="'+name+'" id="'+name+'" '+args+'>')
}
////////////////////////////////////////////////////////////////////////////////
//  Name:        AddHiddenInput
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddHiddenInput = function (name, value)
{
  this.dataTableBody.appendChild (
    CreateElement ('<input type="hidden" name="'+name+'" id="'+name+'" value="'+value+'">'))
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        CreateInput
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.CreateInput = function (type, name, value, length, size,
  dataValidation, onChange, isRequired, requiredText, rebootOnChange,
  condition, parameters)
{
  var dataValidationCmds = ""
  var onChangeCmds = ""
  var thisObj = 'document.getElementById(\''+name+'\')'
  var requiredFunc = (isRequired) ? 
    'VerifyNotBlank ('+thisObj+', \''+requiredText+'\')' : ""
  var newElement
  
  if (onChange == null) onChange = ""
  AddToAndList (onChange, "UpdateDependentRows (this)")
  // if the type is range the real type is still input but we need to add
  // paramaters to the validation function 
  if (dataValidation)
  {
    dataValidation += '('+thisObj
     if (parameters && parameters != "") dataValidation += ", " + parameters
       dataValidation += ')'
  }
  if (length == null) length = ""
  if (size == "max")
  {
    size = kMaxEditBoxLength
  }
  else if (size == null)
  {
    size = Math.min ((length == "") ? "" : length * 1.4, kMaxEditBoxLength)
  }
   
  dataValidationCmds = AddToAndList (dataValidationCmds, dataValidation, requiredFunc)
  onChangeCmds = AddToAndList (onChangeCmds, "page.UpdateCommonAttributes (this)",
                               "ValidateField (this)", onChange)
  if (onChangeCmds != "") onChangeCmds = "return ("+onChangeCmds+")"
  //alert ("dataValidationCmds = \""+dataValidationCmds+"\"")
    
  newElement = CreateElement ('<input name="'+name+'" type="'+type+'" id="'+
    name+'" vFunction="'+dataValidationCmds+'" onchange="'+onChangeCmds+
    '" value="'+value+'" size="'+size+'" maxlength="'+length+'">')
  this.SetCommonAttributes (newElement, rebootOnChange, condition)
  return newElement
}

////////////////////////////////////////////////////////////////////////////////
//  Name:       AddDomainNameEditBox 
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddDomainNameEditBox = function (name, value, length, size, onChange,
  isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "ValidateLANDomainName",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:       AddIPorDomainNameEditBox 
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddIPorDomainNameEditBox = function (name, value, length, size, onChange,
  isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "IPorDomainNameOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddIPEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddIPEditBox = function (name, value, length, size, onChange,
  isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "IpOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddDialingPrefixEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddDialingPrefixEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "DialingPrefix",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddIntegersOnlyEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddIntegersOnlyEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "IntegersOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddNumbersOnlyEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddNumbersOnlyEditBox = function (name, value, length,
  size, onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, "NumbersOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddRangeEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddRangeEditBox = function (name, value, start, end, length,
  size, onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return  this.AddEditBox (name, value,
    (!length ? GetNumberOfDigits(end) : length),
    size, "CheckIntRange",
    onChange, isRequired, requiredText, rebootOnChange,
    condition, start + ", " + end)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddKeyboardOnlyEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddKeyboardOnlyEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return  this.AddEditBox (name, value, length, size, "KeyboardInputOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddKeypadOnlyEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddKeypadOnlyEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return  this.AddEditBox (name, value, length, size, "KeypadOnly",
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddLink
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddLink = function (link, label, style)
{
  var newElement;
  var newOption;
  if (!style) style = ""

  newElement = CreateElement ('<a class="'+style+'" href="'+link+'">');
  newElement.innerText = label; // TODO: Fix NS
  return newElement;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddPageLabel
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddPageLabel = function ()
{
  var titleObj = parent.document.getElementById ("pageTitle")
  titleObj.innerHTML = this.pageName;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddPasswordEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddPasswordEditBox = function (name, value, length, size, 
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.CreateInput ("password", name, value, length, size, "VerifyPassword",
  onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddISDNNumberEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddISDNNumberEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, 'CheckISDNInput',
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddPhoneNumberEditBox
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddPhoneNumberEditBox = function (name, value, length, size,
  onChange, isRequired, requiredText, rebootOnChange, condition)
{
  return this.AddEditBox (name, value, length, size, 'CheckPhoneInput',
    onChange, isRequired, requiredText, rebootOnChange, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddRow
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddRow = function ()
{
  var newRow = new Row ()
  var rowArgs = arguments
  
  // Parse out the arguments
  newRow.SetRowNumber (this.currentRow)
  // Save the form that this is in so that we add to the
  // correct part of the DOM tree.
  newRow.dataTable = this.dataTableBody
  newRow.useColumns = this.useColumns
  for (var index = 0; index < arguments.length; index++)
  {
    // Ignore null fields. Don't ignore empty strings.
    if (rowArgs[index] == null) continue
    
    // Look for command arguments.
    if (typeof rowArgs[index] == "string" &&
        /^[^ =]+=.+$/.test(rowArgs[index]))
    {
      var args = rowArgs[index].split("=")
      if (/(onchangeof)/i.test(args[0]))
      {
        newRow.dependentObjects.push (args[1])
      }
      else
      {
        newRow.SetAttribute (args[0], args[1])
      }
    }
    else
    {
      var newObject = (typeof rowArgs[index] == "string") ?
        eval(rowArgs[index]) : rowArgs[index]
      // eval'ing the string may return null. If it does then 
      // do not add the object.
      if (newRow)
      {
        SetRowValue (newObject, this.currentRow)
        newRow.objects[newRow.objects.length] = newObject
      }
    }
    // The rest of the arguments are objects.
  }
  // Save the row data
  this.rows[this.currentRow++] = newRow
  // alert (newRow.rowNumber + ": " + this.rows[newRow.rowNumber])
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddTranslatedText
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddTranslatedText = function (text, id, style, condition)
{
  return this.AddTextNode (TranslateLangConst(text), id, style, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddLabel
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddLabel = function (text, id, style, condition)
{
  return this.AddTextNode (text, id + "_label", style, condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddTextNode
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddTextNode = function (text, id, style, condition)
{
  var textNode
  
  if (!style) style = "textnode"
  if (!id) id = "textnode"+textNodeCount++

  if (!condition) condition = ""
  
  textNode = CreateElement ('<span id="'+id+'" name="'+id+'"'+
    ' class="'+style+'">')
  textNode.innerHTML = text
  this.SetCommonAttributes (textNode, false, condition)
  
  return textNode
}

function SubmitOnChangeToFrom (object, toValue, form)
{
  if (form == null ) form = 0
  
  if (GetObjectValue (object) == toValue || GetObjectOValue (object) == toValue)
  {
    return  (object, form)
  }
  return true
}

function SubmitOnChange (object, form, text)
{
  if (form == null) form = 0
  if (text == null) text = MAKECHANGE_REFRESHES
  
  // Only do the submit if we are not setting the value back to the original value  
  if (GetObjectPValue (object) != GetObjectValue (object))
  {
    if (confirm (text))
    {
      document.forms[form].submit ()
    }
    else
    {
      ResetObjectToPreviousValue (object)
      return false
    }
  }
  return true
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddRadioList
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddRadioList = function (name, values, selectedValue,
  onChange, isRequired, requiredText, rebootOnChange, multiLine,
  choiceFile, condition)
{
  var options
  var sOption
  var aOption
  var index
  
  if (choiceFile == null) choiceFile = name
  if (onChange == null) onChange = "";
  
  onChange += ";UpdateDependentRows (this);"
  
  if (multiLine == null) multiLine = true;
  var newElement = document.createDocumentFragment()
  
//  if (rebootOnChange, condition) AddFootnoteIndecator ()

  if (values != null && values != "")
  {
    options = values.split ("?")
    for (index = 0; index < options.length; index++)
    {
      aOption = options[index].split("|")
      var text = TranslateOption (choiceFile, aOption[1])
      var value = aOption[0]
      var newOption = CreateElement 
        ('<input type="radio" id="'+name+'" name="'+name+'" onclick="'+onChange
         +'" value="' + value + '"' +((value == selectedValue) ? ' checked' : '')+'>')

      newOption.checked = (value == selectedValue)
      this.SetCommonAttributes (newOption, rebootOnChange, condition)
      newElement.appendChild (newOption)
      newElement.appendChild (
        (/(\.gif|\.png)$/.test (text)) ? 
          CreateElement ('<img src="'+text+'" border="0" hspace="1">') : 
          this.AddTextNode (text))
      if (multiLine) newElement.appendChild (CreateElement ('<br>'))
    }
  }

  return newElement;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddSelect
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddSelect = function (name, values, onChange, rebootOnChange, 
  choiceFile, selectedValue, condition)
{
  var options;
  var sOption;
  var aOption;
  var index;
  var newElement;
  var newOption;
  var text
  var defaultValue = ""
  var isFistLineADup = false
  var selectedIndex = 0
    
  if (!values) return null
    
  if (choiceFile == null) choiceFile = name
  if (onChange == null) onChange = "";
  onChange += ";page.UpdateCommonAttributes (this);UpdateDependentRows (this);"

   options = values.split ("?")
   // If there is only one choice create a text node instead of a drop down box.
   // The dynamically created serial port choice file some times have the same
   // value twice once to indecate that it is the default and once as the valid choice.
   if (options.length == 1 || (options.length == 2 && 
     options[0].split ("|")[0] == options[1].split ("|")[0]))
   {
     return this.AddTextNode (TranslateOption (choiceFile, options[0].split ("|")[0]), name)
   }
   
   // Create the select
   newElement = CreateElement ('<select align="absmiddle" id="'+name+'" name="'+name+'" onchange="'+onChange+'">')

   for (index = 0; index < options.length; index++)
   {
     aOption = options[index].split("|")
     newOption = newElement.appendChild (CreateElement('<option value="'+aOption[0]+'">'))
     // Since we now have access to all of the tranlated string constants.
     // We no longer need to rely on the server sending them to us.
     newOption.text = TranslateOption (choiceFile, aOption[0])
     // Once the server has been modified to not send the translated value
     // the line below can replace the line 2 rows down.
     // newOption.selected = aOption.length > 1
     if ((selectedValue && (selectedValue == aOption[0])) || 
       (!selectedValue && (aOption.length > 1 && aOption[aOption.length-1] == kSelected)))
         selectedIndex = index
     // alert (newOption.text + " is selected = " + newOption.selected )
     // If this is the first line save it as the default
     if (index == 0)
     {
       defaultValue = newOption.value
     }
     // If this is not the first line check to see if it is a dup of the first line
     // so that we can remove the fist line when we are done.
     else
     {
       if (!isFistLineADup) isFistLineADup = newOption.value == defaultValue
     }
   }

   if (isFistLineADup)
   {
     newElement.options[0] = null
     if (selectedIndex != 0) --selectedIndex
   }
 
   newElement.selectedIndex = selectedIndex
  
  this.SetCommonAttributes (newElement, rebootOnChange, condition)

  return newElement;
}

//////////////////////////////////////////////////////////////////////
//  Name:        GetButtonElement
//  Description: Get the Button Element
//////////////////////////////////////////////////////////////////////

Page.prototype.GetButtonElement = function ()
{
  return parent.document.getElementById ("buttons")
}

//////////////////////////////////////////////////////////////////////
//  Name:        AddHeaderButton
//  Description: Add buttons to the header
//////////////////////////////////////////////////////////////////////

Page.prototype.AddHeaderButton = function (button)
{
  var buttonElement = this.GetButtonElement ()
  if (!buttonElement)
  {
    parent.page.AddHeaderButton (button)
    return
  }
  buttonElement.insertAdjacentElement ("beforeend", button)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        AddUpdateNextButtons
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.AddUpdateNextButtons = function (backPage,
  nextPage, showUpdate, onSubmit, contentPage)
{
  var buttonElement = document.getElementById ("buttons")
  if (!buttonElement)
  {
    parent.page.AddUpdateNextButtons (
      backPage, nextPage, showUpdate, onSubmit, this)
    return
  }
  
  if (contentPage == null) contentPage = this
  var form = this.formName ? "'" + contentPage.formName + "'" : "null"
  
  RemoveChildren (buttonElement)

  //alert (onClick);
  if (showUpdate == null) showUpdate = (!isOOB && contentPage.formName)
  if (nextPage == null) nextPage = "";
  if (!onSubmit) onSubmit = "";

  if (showUpdate)
  {
    buttonElement.appendChild (this.CreateButton ("update", UPDATE,
      "page.CheckAndSubmitForm('"+onSubmit+"', "+form+")"))
  }
  if (backPage)
  {
    buttonElement.appendChild (this.CreateButton ("back", MENU_STR,
      "if (isOOB) {TurnOffOOB ()};page.OnClickBackNext('"+backPage+"', '"+onSubmit+"', "+form+")"))
  }
  if (nextPage != "")
  {
    buttonElement.appendChild (this.CreateButton ("next", NEXT_STR,
      "if (VerifyNext()) page.OnClickBackNext('"+nextPage+"', '"+onSubmit+"', "+form+")"))
  }
}

function ButtonMouseOver (name, style)
{
  document.getElementById(name+"left").className = style+"leftover"
  document.getElementById(name+"middle").className = style+"middleover"
  document.getElementById(name+"right").className = style+"rightover"
}

function ButtonMouseOut (name, style)
{
  document.getElementById(name+"left").className = style+"left"
  document.getElementById(name+"middle").className = style+"middle"
  document.getElementById(name+"right").className = style+"right"
}

Page.prototype.CreateButton = function (name, value, onclick, style)
{
  var newButton
  var newButtonTable
  var buttonLeft
  var buttonMiddle
  var buttonRight

  if (!style) style = "button"
  
  newButtonTable = CreateElement ('<table id="'+name+'" name="'+name+'" class="'+style+'">')
  newButton = newButtonTable.appendChild (
    CreateElement('<tbody class="'+style+'">'))
  newButton = newButton.appendChild (CreateElement('<tr class="'+style+'">'))
  buttonLeft = CreateElement
    ('<td id="'+name+'left" name="'+name+'left" '+
      'onMouseOver="ButtonMouseOver (\''+name+'\', \''+style+'\')" '+
      'onMouseOut="ButtonMouseOut (\''+name+'\', \''+style+'\')" '+
      'class="'+style+'left" onClick="'+onclick+'">')
  buttonLeft.innerHTML = "&nbsp;"
  buttonMiddle = CreateElement
    ('<td id="'+name+'middle" name="'+name+'middle" '+
      'onMouseOver="ButtonMouseOver (\''+name+'\', \''+style+'\')" '+
      'onMouseOut="ButtonMouseOut (\''+name+'\', \''+style+'\')" '+
      'class="'+style+'middle" onClick="'+onclick+'">')
  buttonMiddle.innerHTML = value
  buttonRight = CreateElement
    ('<td id="'+name+'right" name="'+name+'right" '+
      'onMouseOver="ButtonMouseOver (\''+name+'\', \''+style+'\')" '+
      'onMouseOut="ButtonMouseOut (\''+name+'\', \''+style+'\')" '+
      'class="'+style+'right" onClick="'+onclick+'">')
  buttonRight.innerHTML = "&nbsp;"

  newButton.appendChild ((g_direction == "ltr") ? buttonLeft : buttonRight)
  newButton.appendChild (buttonMiddle)
  newButton.appendChild ((g_direction == "ltr") ? buttonRight : buttonLeft)

  return newButtonTable
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        CreateHeaderTable
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.CreateHeaderTable = function ()
{
  var headerTable = 
    CreateElement ('<table id="headerTable" width="100%" border="0" cellspacing="0" cellpadding="2">')
  var tbody = headerTable.appendChild (CreateElement ('<tbody>'))
  var headerRow = tbody.appendChild (CreateElement('<tr class="pageTitle">'))
  
  headerRow.appendChild(CreateElement('<td class="pageTitle" id="pageTitle">'))
  headerRow.appendChild(CreateElement('<td name="buttons" id="buttons">'))
  
  return headerTable;
}


function SetAttributeValue (object, attribute, value)
{
  if (object)
  {
    if (object.setAttribute)
    {
      object.setAttribute (attribute, value)
    }
    if (object.hasChildNodes && object.hasChildNodes ())
    {
      //alert ("HasChildNodes")
      for (var child = 0; child < object.childNodes.length; child++)
      {
        SetAttributeValue (object.childNodes.item(child), attribute, value)
      }
    }
  }
}

function GetAttributeValue (object, attribute)
{
  var rValue = null
  
  if (object)
  {
    if (object.getAttribute)
    {
      rValue = object.getAttribute (attribute)
    }
    else if (object.hasChildNodes && object.hasChildNodes ())
    {
      //alert ("HasChildNodes")
      for (var child = 0; child < object.childNodes.length; child++)
      {
        rValue = GetAttributeValue (object.childNodes.item(child), attribute)
        if (rValue != null) break
      }
    }
  }
  return rValue
}

function SetRowValue (object, row)
{
  if (GetAttributeValue (object, "row") == -1)
  {
    SetAttributeValue (object, "row", row)
  }
}

function ShowObj (object)
{
  var bRValue = false
  if (object)
  {
    var objCondition = GetAttributeValue (object, "condition")
    objCondition = (objCondition) ? objCondition : ""
    bRValue = (objCondition == "" || eval (objCondition))
  }
  return bRValue
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        UpdateLabel
//  Description: Update the label element of a row
////////////////////////////////////////////////////////////////////////////////

Page.prototype.UpdateLabel = function (row, newValue)
{
  var labelId = row + "label"
  var label = document.getElementById(labelId)
  if (label) label.innerHTML = newValue
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        CreateFootnoteIndecator
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.CreateFootnoteIndecator = function ()
{
  return document.createTextNode(" *")
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        RegisterForChanges
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.RegisterForChanges = function (dependentObjects, rowNumber)
{
  var row
  var index
  var objects
  var object
  var isDup
  var dependentRows
  
  // alert ("Register row " + rowNumber + " for changes to "+dependentObjects)
  
  for (index in dependentObjects)
  {
    // object = document.getElementById (dependentObjects[index])
    object = this.FindObjectById (dependentObjects[index])
    isDup = false
    // Don't add a row more than once.
    if (object)
    {
      dependentRows = GetArrayAttribute (object, kDependentRows)
      for (row in dependentRows)
      {
        if (dependentRows[row] == rowNumber)
        {
          isDup = true
          break
        }
      }
      if (!isDup)
      {
        dependentRows.push (rowNumber)
        dependentRows.sort (numberorder)
        SetArrayAttribute (object, kDependentRows, dependentRows)
        this.RegisterForChanges (this.rows[object.getAttribute ("row")].dependentObjects, rowNumber)
      }
    }
  }
}

function FindObjectById (object, id)
{
  var results
  //alert ("FindObjectById ("+object+", "+id+")")
  if (object)
  {
    if (object.id)
    {
      // alert ("FindObjectById : object.id = "+object.id+" looking for "+id)
      if (object.id == id) return object
    }
    if (object.hasChildNodes ())
    {
      //alert ("HasChildNodes")
       for (var child = 0; child < object.childNodes.length; child++)
      {
        results = FindObjectById (object.childNodes.item(child), id)
        if (results != null) return results
      }
    }
  }
  return null
}

Page.prototype.FindObjectById = function (id)
{
  var rowIndex
  var objectIndex
  var resultsObj
  
  for (rowIndex in this.rows)
  {
    for (objectIndex in this.rows[rowIndex].objects)
    {
      resultsObj = FindObjectById (this.rows[rowIndex].objects[objectIndex], id)
      if (resultsObj) {/*alert ("FindObjectById ("+id+") : FOUND");*/return resultsObj}
    }
  }
  return null
}

function SetArrayAttribute (object, attribute, arrayValues)
{
  var aValue = ""
  for (var arrayValue in arrayValues)
  {
    if (aValue != "") aValue += kAttributeSeperator
    aValue += arrayValue + kAttValueSeperator + arrayValues [arrayValue]
  }
  // alert ("Saving " + attribute + " as \"" + aValue + "\"")
  object.setAttribute (attribute, aValue)
}

function GetArrayAttribute (object, attribute)
{
  var values = object.getAttribute (attribute)
  var results = new Array ()
  var valueAttPairs = values.split (kAttributeSeperator)
  
  // alert ("values = \"" + values + "\"")
  if (values != "")
  {
    for (var valueAttPair in valueAttPairs)
    {
      valueAndAttributes = valueAttPairs[valueAttPair].split (kAttValueSeperator)
      results [valueAndAttributes[0]] = valueAndAttributes[1]
    }
  }
  // alert ("Getting " + attribute + " as \"" + results + "\"")
  return results
}

function GetBooleanAttribute (object, attribute)
{
  var value = (object)?object.getAttribute (attribute):"false";
  
  // getAttribute in NS and Firefox only returns string so we need to convert
  // to boolean
  if (typeof value == "string") return value == "true"
  else return value
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.UpdateCommonAttributes = function (object)
{
  var currentValue = GetObjectValue (object)
  var oldCurrentValue = GetObjectCValue (object)
  var pageObj = this.FindObjectById (object.id)
  
  // Update previous value to the old current value
  object.setAttribute ("pValue", oldCurrentValue)
  // Update the current value with the objects actual value
  object.setAttribute ("cValue", currentValue)

  if (pageObj)
  {
    // Now do the same for row data so if we remove and add this element
    // we do not loss this data
    pageObj.setAttribute ("pValue", oldCurrentValue)
    pageObj.setAttribute ("cValue", currentValue)
    SetObjectValue (pageObj, currentValue, false)
  }
  return true
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        SetCommonAttributes
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.SetCommonAttributes = function (objectID, rebootOnChange, condition)
{
  var object = objectID;
  rebootOnChange = (rebootOnChange == true)// Check for true in case it is null
  
  if (object)
  {
    var value = GetObjectValue (object)
    object.setAttribute ("oValue", value)
    object.setAttribute ("cValue", value)
    object.setAttribute ("pValue", value)
    object.setAttribute ("rebootOnChange", rebootOnChange)
    object.setAttribute ("row", -1)
    if (rebootOnChange) this.bootOnSomeChanges = true
    SetArrayAttribute (object, kDependentRows, new Array ())
    object.setAttribute ("condition", (condition) ? condition : "")
  }
  return object
}

Page.prototype.GetGroup = function (form)
{
  var groupObj = document.forms[(!form) ? this.formName : form]._groupname
  return document.forms[(!form) ? this.formName : form]._groupname.value
}
Page.prototype.SetGroup = function (group, form)
{
  document.forms[(!form) ? this.formName : form]._groupname.value = group
}

Page.prototype.SetAction = function (action, form)
{
  document.forms[(!form) ? this.formName : form].action = action
}

Page.prototype.GetAction = function (form)
{
  return document.forms[(!form) ? this.formName : form].action
}

Page.prototype.Submit = function (form)
{
  document.forms[(!form) ? this.formName : form].submit ()
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        ShowHideRow
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Page.prototype.ShowHideRow = function (rowIndex)
{
  var rowData = this.rows[rowIndex]
  var oldRow
  var previousRow = null;
  var newRow
  var rowID = rowData.GetRowID ()
  var index
  
  if (rowData.Show ())
  {
    // If the element does not exits add it
    oldRow = document.getElementById (rowID)
    newRow = rowData.CreateRow ()
    if (oldRow == null)
    {
      // Find the fist row that exists before the postion we want to add this row.
      for (index = rowData.rowNumber - 1; previousRow == null && index >= 0; index--)
      {
        previousRow = document.getElementById (this.rows[index].GetRowID());
      }
      // If previous row is still null we are going to add this elemnt to the top
      if (previousRow == null) previousRow = rowData.dataTable
      previousRow.insertAdjacentElement ("afterEnd", newRow)
      if (rowData.oncreationof) eval (rowData.oncreationof)
    }
    // If it does exist update it to the new one
    else
    {
      oldRow.replaceNode (newRow)
    }
    if (rowData.onshow) eval (rowData.onshow)
  }
  // otherwise hide it
  else
  {
    // If the element exists remove it
    if (document.getElementById (rowID) != null)
    {
      RemoveElements (rowID);
      if (rowData.onhide) eval (rowData.onhide)
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        Row
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

function Row ()
{
  this.tabed = page.currentIndent
  this.style = null
  this.labelstyle = ""
  this.datastyle = ""
  this.dataColumns = 1
  this.columns = 1
  this.width = "40%"
  this.condition = null
  this.objects = new Array ()
  this.rowNumber = null
  this.dependentObjects = new Array ()
  this.oncreation = null
  this.dataTable = null
  this.useColumns = false
  this.name = ""
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        CreateRow
//  Description: Create a new row object
////////////////////////////////////////////////////////////////////////////////

Row.prototype.CreateRow = function ()
{
  var index
  var newElement
  var rowElement = null
  var newNode
  var rowId = this.GetRowID ()
  var dataId = this.GetDataID ()
  var labelId = this.GetLabelID ()
  var labelStyle = (this.labelstyle) ? this.labelstyle : 
    (this.style) ? this.style : "defaultRow"
  var dataStyle = (this.datastyle) ? this.datastyle :
    (this.style) ? this.style : "defaultData"
  var objCondition
   
  if (this.Show ())
  {
    var noWrap = (this.columns == 1) ? "nowrap " : ""
  
    rowElement = CreateElement ('<tr id="'+rowId+'" class="'+this.style+'">')
    
    // Create the label
    newTD = CreateElement ('<td '+noWrap+'colspan="'+this.columns+'" id="'+
        labelId+'" class="'+labelStyle+'">')
    newTD.noWrap = (this.columns == 1)
    newElement = rowElement.appendChild (newTD)
    for (index = 0; index < this.tabed; index++)
    {
      newElement.insertAdjacentHTML ("afterBegin", "&nbsp;&nbsp;&nbsp;&nbsp;")
    }
    
    for (index = 0; index < this.objects.length; index++)
    {
      var labelObj = this.objects[index]
      // If the object is empty or null leave the label empty
      if  (labelObj == "" || labelObj == null) break
      // Otherwise showt the first object that does not have its
      // condition set to false.
      if (ShowObj (labelObj))
      {
        newElement.appendChild (labelObj.cloneNode (true))
        break
      }
    }

    // If we are not using columns crate the td outside of the loop
    if (!this.useColumns) newElement = rowElement.appendChild (CreateElement
      ('<td colspan="'+this.dataColumns+'" id="'+dataId+'" class="'+dataStyle+'">'))

    for (++index; index < this.objects.length; index++)
    {
      // If we are using columns then we need to create a new td for each element.
      if (this.useColumns)
      {
        newElement = rowElement.appendChild (
          CreateElement ('<td id="'+dataId+(index-1)+'" class="'+dataStyle+'">'))
      }
      else
      {
        if (index != 1) newElement.appendChild (document.createTextNode(" "))
      }
      
      if (ShowObj (this.objects[index]))
      {
        // Create the object
        newNode = this.objects[index].cloneNode (true)

        // The selected object was not being copied. Maybe we need to us a documentFragment
        if (this.objects[index].selectedIndex)
          newNode.selectedIndex = this.objects[index].selectedIndex
        
        // Add the object
        newElement.appendChild (newNode)
      
        // Add a star at the end of the element if changing it will cause a reboot.
        if (RebootOnChange (this.objects[index]))
        {
          var footnoteIndecator = page.CreateFootnoteIndecator ()
          newElement.appendChild (footnoteIndecator)
        }
      }
    }
  }
  return rowElement;
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        GetRowID
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Row.prototype.GetRowID = function ()
{
  return (this.name == "") ? "row" + this.rowNumber : this.name
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        GetLabelID
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Row.prototype.GetLabelID = function ()
{
  return this.GetRowID () + "label"
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        GetDataID
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Row.prototype.GetDataID = function ()
{
  return this.GetRowID () + "data"
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        SetAttribute
//  Description: Used to set an arbitrary row attribute
////////////////////////////////////////////////////////////////////////////////

Row.prototype.SetAttribute = function (attribute, value)
{
  this[attribute] = value
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        SetRowNumber
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

Row.prototype.SetRowNumber = function (rowNumber)
{
  this.rowNumber = rowNumber
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        Show ()
//  Description: Return true if the rows condition attribute evaluates to true
////////////////////////////////////////////////////////////////////////////////

Row.prototype.Show = function ()
{
  return !this.condition || eval (this.condition)
}

////////////////////////////////////////////////////////////////////////////////
//  Name:        UpdateDependentRows
//  Description: Description
////////////////////////////////////////////////////////////////////////////////

function UpdateDependentRows (object)
{
  var dependentRows = GetArrayAttribute (object, kDependentRows)
  //alert ("UpdateDependentRows ("+object.id+") : " + dependentRows)
  
  for (var index = 0; index < dependentRows.length; index++)
  {
    page.ShowHideRow (dependentRows [index])
  }
}
