<!--

/***********************************************************************************************************************
   The following file is used to validate form fields.
   Filename: validateForms.js
   Author: Manuel Navarro

   Setup:
   You can load this file onto an HTML, or ASP document that contains a form and
      it's fields have the appropriate attributes (explained later). This file will
      search through those fields, looking for certain matches in the field attribute
      and setup an error message or way to display an error message if the field is not
      validated.
   
   Field attributes (possible values):
   Below are possible values you can set on the fields of a form (each is explained)

   required - Must be present in order for a form to validate the field. Remove to omit validation.
                  This option supersedes 'optional'
   optional - If this is present and a fields's value is not empty, the form will validate that field.
                  This option does not supersede required.
   errormessage - Error message you would like to give the user (optional)
   validationexpression - Regular expression used to validate the field. (optional)
         NOTE: ONLY flags can be set at the end of the expression with a backslash and a letter combination:
               /i, /g, /m, /gi and so on...
   display - Set display options here (In order of importance):
      summary     -  Shows any error messages associated with a control in each of the summaryIDs' array objects.
                        summaryIDs must be a valid array and contain valid element id's. If summaryIDs is invalid
                        then the default popup will be used.
      noblur      -  Specifies that the field should not be validated when an "onblur" even happens.
      nofocus     -  Specifies not to focus on the invalid field.
      pop/popup   -  Creates a popup box for showing error messages. Overrides all other display options except noblur.
      parent      -  Creates label above field and before the fields parent objects first child.
      top         -  Creates label directly above field
      dyn/dynamic -  The label is hidden by block style (unlike the others, where it is hidden only in visibility)
      other/blank -  Leaving display blank, or having a value other than the ones listed here (besides
                        noblur and dynamic) will cause the error label to appear at the bottom of the fields parent.
   novalidation  - Can be set on a <form> tag to indicate the form should not be validated when submitted.
   
   Display values can be combined, for instance, you can combing "pop noblur", "parent dynamic noblur", "top dynamic"... etc.
   
   Example:
   This is how to setup this object:

   <form id="form1" action="page.html">
      <label for="textbox">Required</label>
      <input id="textbox" type="text"
         required
         errormessage="This field is required"
         validationexpression="^[\w]/i"
         display="parent dynamic" />
      <input type="submit" />
   </form>

   That is a simple form that will check (through regular expression) whether there is a word value in the textbox field.
   If there is not, a dynamic displaying label will alert the user either when the form is submitted or they blur away
      from the textbox field.

   '''''''''''''''' SUMMARY LAYERS '''''''''''''''''
   To add summary layers to the summaryIDs array, do the following after referencing this script on your web pages:

      <script type="text/javascript">
         vforms.summaryIDs = new Array();
         vforms.summaryIDs.push("LAYER_1_ID_HERE");
         vforms.summaryIDs.push("LAYER_2_ID_HERE");
      </script>

   NOTE: If the summary layers cannot be found then the error will display by default in a popup.
   '''''''''''''''''''''''''''''''''''''''''''''''''
   
   Final notes:
   The ValidationExpression field CAN be excluded, however, the only validation that will take place is checking whether
      or not the field is blank.
   CSS Styles should be already be written and defined before using the pop option. Please note that all of the styles
      associated with the popupClasses should have their positions set to 'absolute'

   Versions:
      0.7   -  11/6/08
               Forms that have an attribute of 'novalidation' will not be validated when they are submitted.
               This is helpful for AJAX forms or ASAP forms that have validation controls or if you want
                  to call each fields validation individually through javascript.
      0.6   -  09/04/08
               Added the display='summary'option to display error labels in summary div's defined in the new
               summaryIDs array object. Read above for how to add summary labels to this array.
      0.5   -  06/27/07
               Added the Optional tag (these fields will only be checked if they are not empty)
               popupArrow height and width are now set through the image's offsetHeight and offsetWidth values
                  uppon creation of the popup box, making it easier to set different images and styles.
      0.4   -  06/20/07
               Uncommented required functions so that this file can be used by itself.
      0.3   -  06/12/07
               Finished object to date. Options include: normal/blank, noblur (new), pop, parent, top, and dynamic.
               Wrote out instructions and information about file. Added and commented out required functions.
               Added setfocus to validation, added focus display options
      0.2   -  06/11/07
               Wrapped in an object, added popup box, added more initialization variables
      0.1   -  06/10/07
               Basic javascript planning
************************************************************************************************************************/


var vforms = {
   // NOTE: The following are only defaults. They can be changed after loading the Script.
   //
   // Initialize some common variables
   formAutoGenID: "frmAutoGeneratedID",   // ID Name
   formAutoGenNum: 0,                     // Start ID number
   // Dynamic box classnames as an array (Arrows are always first two
   popupClasses: new Array("mbubble", "arrow_out", "arrow_in", "container", "middle", "bottom", "closebutton"),
   // close button image
   popupCloseImage: "http://framework.communitycollege.org/images/close_button_16x16.gif",
   // Popup arrow width and height, left offset from parent.
   //    The third element popupArrow(3) should be the height of the shadow on the bottom edge
   //       of the bottom image. If no shadow is present or the edge of the bottom image is 
   //       directly at the bottom then that value should be zero.
   popupArrow: new Array(0, 0, 25, 8),
   // Popup box width (also bottom edge "image" height and padding to move box closer to field)
   popupBox: new Array(280, 13),
   // Default display view for objects
   defaultDisplay: "pop",
   // Error label classname
   labelClass: "vforms_errorlabel",
   // Error classname for the parent object
   parentErrorClass: "vforms_parenterror", // Set to blank if no error class is desired

   // Validation Summary Node List
   summaryIDs: null,

   // The following should not be changed
   popupList: new Array(),
   popupShowing: false,

   oldWinHeight: 0,     // Old Window Height
   oldWinWidth: 0,     // Old Window Width

   // Detects Windows Internet Explorer version
   isIE:
   function()
   {
      // Detect IE name first
      var ieName = navigator.appName;
      ieName = (ieName.indexOf("Internet Explorer") != -1) ? true : false;
      if(!ieName) return false;  // Return false if IE Name is not detected

      // Return true if version is less than 7
      var ieVersion = navigator.appVersion;
      ieVersion = ieVersion.substring(ieVersion.indexOf("MSIE")+4);
      return parseFloat(ieVersion);
   },

   setupForms:
   function()
   {
      var p, curParent, pID;
      var objforms = document.getElementsByTagName("form");

      for(p = 0; p < objforms.length; p++)
      {
         curParent = objforms[p];
         pID = curParent.getAttribute("id");
         // Make sure the form has an ID associated with it.
         if(pID == null || pID == "")
         {
            pID = vforms.formAutoGenID + (vforms.formAutoGenNum++);
            curParent.setAttribute("id", pID);
         }

         // Create a checklist for the current form
         curParent.checkList = new Array();
         vforms.setupChildren(curParent, curParent);
         // Only add the submit function if the form does not have
         //    a nosubmit attribute
         if(curParent.getAttribute("novalidation") == null)
            addEvent(curParent, "submit", vforms.validateOnSubmit, false);
      }
   },

   setupChildren:
   function(curParent, defParent)
   {
      // Check to make sure summaryIDs is an actual array
      if(!vforms.summaryIDs || !vforms.summaryIDs.length)
         vforms.summaryIDs = new Array();
      else
      {
         // If it is an array then check it's length and hide all the summary displays
         if(vforms.summaryIDs.length > 0)
         {
            // Loop through each summary layer and hide it. If this function
            //    returns false then that means the summary layers were not
            //    found. So if that happens, set summaryIDs to a null value.
            if(!vforms.displayErrorSummary(null, true))
               vforms.summaryIDs = null;
         }
      }

      var c, curChild, cLen, pListNum;
      var cID, cDoCheck, cErrMsg, cValExp, cDisplay;
      pListNum = defParent.checkList.length;

      cLen = curParent.childNodes.length;

      for(c = 0; c < cLen; c++)
      {
         curChild = curParent.childNodes[c];
         if(curChild.formParent) continue;  // Current child has already been checked. Skip.

         // Setup children of this child if there are any
         if(curChild.childNodes.length > 0) vforms.setupChildren(curChild, defParent);
         // Don't go any farther if this child is not required/optional to be validated
         cDoCheck = (curChild.getAttribute) ? curChild.getAttribute("required") : null;
         // Check optional if required was not found.
         cDoCheck = (cDoCheck == null && curChild.getAttribute) ? curChild.getAttribute("optional") : cDoCheck;
         if(cDoCheck == null) continue;

         // Might not need the name/id or type
         cID = curChild.name;
         cID = (cID == "" || !cID) ? curChild.getAttribute("id") : cID;
         cID = (cID == "" || !cID) ? curChild.type : cID; // nothing found

         cErrMsg = curChild.getAttribute("ErrorMessage");
         cErrMsg = (cErrMsg == "" || !cErrMsg) ? "'" + cID + "' is a required field." : cErrMsg;
         curChild.errMsg = cErrMsg; // Set value on the actual object

         cValExp = curChild.getAttribute("ValidationExpression");
         cValExp = (cValExp == "" || !cValExp) ? false : cValExp;
         curChild.valExp = cValExp; // Set value on the actual object

         cDisplay = curChild.getAttribute("Display");
         cDisplay = (cDisplay == "nofocus" || cDisplay == "noblur") ?
                           vforms.defaultDisplay + cDisplay : cDisplay;
         cDisplay = (cDisplay == "" || !cDisplay) ? vforms.defaultDisplay : cDisplay // Default should be defined already
         // Check for validation summary display and if valSummaryIDs is set
         cDisplay = (cDisplay.indexOf("sum") != -1 &&
                     (vforms.summaryIDs.length <= 0)) ? vforms.defaultDisplay : cDisplay;
         curChild.errPos = cDisplay.toLowerCase(); // Set value on the actual object

         // Create popup object here
         if(cDisplay.indexOf("pop") != -1)
         {
            // Add focus in event to hide the popup
            addEvent(curChild, "focus", vforms.hidePopupOnFocus, false);

            // Add focus out event to hide the popup
            if(cDisplay.indexOf("noblur") == -1)
               addEvent(curChild, "blur", vforms.hidePopupOnFocus, false);

            // Create popup box
            if(!defParent.popup) vforms.createPopup(defParent);
         }

         // Add this object to the check list
         defParent.checkList[pListNum++] = curChild;
         // Create error message object for this child
         vforms.createErrorLabel(curParent, curChild);

         // Add onblur function to child object only if cDisplay does not include "noblur"
         if(cDisplay.indexOf("noblur") == -1)
            addEvent(curChild, "blur", vforms.blurEvent, false);
         curChild.formParent = defParent;
      }
   },

   createPopup:
   function(parentObj)
   {
      if(parentObj.popup) return; // Parent already has popup
      var mainDiv = document.createElement("div");
      mainDiv.className = vforms.popupClasses[0];
      mainDiv.style.visibility = "hidden";
      mainDiv.style.block = "none";

         // Create arrow object
         var mainArrow = document.createElement("div");
         mainArrow.className = vforms.popupClasses[1];
            var childArrow = document.createElement("div");
            childArrow.className = vforms.popupClasses[2];
         mainArrow.appendChild(childArrow);
      // Attach arrow object to the main div
      mainDiv.appendChild(mainArrow);

         var boxContainer = document.createElement("div");
         boxContainer.className = vforms.popupClasses[3];
            // Create message div
            var boxMessage = document.createElement("div");
            boxMessage.className = vforms.popupClasses[4];
         // Attach message div to the container
         boxContainer.appendChild(boxMessage);
            // Create footer
            var boxFooter = document.createElement("div");
            boxFooter.className = vforms.popupClasses[5];
         // Attach footer to the container
         boxContainer.appendChild(boxFooter);
            // Create close button
            var closeBox = document.createElement("img");
            closeBox.className = vforms.popupClasses[6];
            closeBox.setAttribute("src", vforms.popupCloseImage);
            closeBox.setAttribute("alt", "Close");
            addEvent(closeBox, "click", vforms.hidePopupOnClick, false);
         // Attach close button to the container
         boxContainer.appendChild(closeBox);

      // Attach the container to the main div
      mainDiv.appendChild(boxContainer);
      document.body.appendChild(mainDiv);

      // If this browser is IE 6 or below, then use the iframe
      //    workaround to make sure this popup stays above 'select' objects
      if(vforms.isIE() && vforms.isIE() < 7)
      {
         var iFrame = document.createElement("iframe");
         iFrame.className = "select_zindex";
         mainDiv.appendChild(iFrame);
         iFrame = null;
      }

      // Now attach these objects to the form
      mainDiv.arrow = mainArrow;
      mainDiv.arrowImg = childArrow;
      mainDiv.box = boxContainer;
      mainDiv.closeBox = closeBox;
      mainDiv.msg = boxMessage;
      mainDiv.formParent = parentObj;
      parentObj.popup = mainDiv;
      // Add this to the popup list
      vforms.popupList[vforms.popupList.length] = mainDiv;

      // Try to get the arrow images height (then cut it in half)
      vforms.popupArrow[1] = (parseInt(childArrow.offsetHeight) > 0) ?
                              (parseInt(childArrow.offsetHeight)/2) : vforms.popupArrow[1];
      // Now try to get the arrow images width value
      vforms.popupArrow[0] = (parseInt(childArrow.offsetWidth) > 0) ?
                              (parseInt(childArrow.offsetWidth)) : vforms.popupArrow[0];

      // Assign these new width and height values to the mainArrow object
      mainArrow.style.width = vforms.popupArrow[0];
      mainArrow.style.height = vforms.popupArrow[1];

      // Finally, try to retrieve the width from the mainDiv's offset or style.
      vforms.popupBox[0] = (parseInt(mainDiv.offsetWidth) > 0) ?
                            parseInt(mainDiv.offsetWidth) :
                              (mainDiv.style.width) ? parseInt(mainDiv.style.width) : vforms.popupBox[0];

      // Clear variables
      mainDiv = mainArrow = childArrow = boxContainer = boxMessage = boxFooter = closeBox = null;
   },

   createErrorLabel:
   function(pObj, cObj)
   {
      if(cObj.errLabel) return;
      var dType = cObj.errPos; // Get label position

      // Exit if the label already exists or if the label is a popup/summary
      if(dType.indexOf("pop") != -1 || dType.indexOf("sum") != -1 || cObj.errLabel)
      {
         cObj.errLabel = true;
         return;  // Exit
      }

      var label = document.createElement("span");
      label.className = vforms.labelClass;
      // Hide the labels visibility
      label.style.visibility = "hidden";
      // Set error message inside of the label
      label.innerHTML = cObj.errMsg;

      // Where to place label:
      if(dType.indexOf("top") != -1 || dType.indexOf("parent") != -1)
         // Check if the top should go top of parent or top of object
         if(dType.indexOf("parent") != -1 && cObj.parentNode) // Make sure the parent node exists
            pObj.insertBefore(label, cObj.parentNode.firstChild);
         else  // Else just attach it normally on top
            pObj.insertBefore(label, cObj);

      else
         (cObj.parentNode) ?
            cObj.parentNode.appendChild(label) : pObj.appendChild(label);

      // Check if the label should be displayed dynamically
      if(dType.indexOf("dyn") != -1) label.style.display = "none";

      cObj.errLabel = label;
   },

   validateOnSubmit:
   function(e)
   {
      var frm = getObject(e);
      if(!frm) return;  // Return if there is no object to check

      // Make sure we can get a checklist
      if(!frm.checkList)
      {
         while(frm.parentNode)
         {
            frm = frm.parentNode;
            if(frm.checkList) break;
         }
      }

      if(!frm.checkList) return true; // Could not find the checklist, return & let form submit

      var curItem, fieldValid = true;
      var checkLen = frm.checkList.length;
      if(checkLen < 1) return true; // Return if nothing has to be checked

      for(var i = 0; i < checkLen; i++)
      {
         curItem = frm.checkList[i];
         fieldValid = vforms.validateField(curItem);
         // Cancel submit
         if(!fieldValid) return vforms.burstBubble(e);
      }
      // Hide the summary boxes if they exist
      vforms.displayErrorSummary(null, true);

      return fieldValid;
   },

   validateField:
   function(curItem, focusEvent)
   {
      // Set the validation to true from the start
      var fieldValid = true;
      // Check default values
      var focusEvent = (focusEvent == null) ? false : focusEvent;

      // Return true if this field is optional and it's value is empty
      if(curItem.getAttribute("optional") != null && curItem.value == "") return true;

      if(curItem.valExp)
         fieldValid = vforms.validByExp(curItem.value, curItem.valExp);
      else
         fieldValid = (curItem.value != "");

      vforms.displayErrorLabel(curItem, fieldValid, focusEvent);  // display or hide error label based on fieldValid value
      return fieldValid;
   },

   displayErrorLabel:
   function(curItem, hide, focusEvent)
   {
      var dType, errLabel;
      // Check default values
      var focusEvent = (focusEvent == null) ? false : focusEvent;

      dType = curItem.errPos;
      errLabel = curItem.errLabel;

      // Change the parent objects error class if the classname is set
      if(vforms.parentErrorClass != "")
      {
         // Get node's parent object
         var parentNode = curItem.parentNode;

         if(parentNode != null && !hide && parentNode.className.indexOf(vforms.parentErrorClass) == -1)
            parentNode.className += " " + vforms.parentErrorClass;
         else if(hide)
         {
            // Remove parent objects error class
            var re = new RegExp(vforms.parentErrorClass, "g");
            parentNode.className = parentNode.className.replace(re, "");
         }
      }

      if(dType.indexOf("pop") == -1)
      {
         if(dType.indexOf("sum") != -1)
         {
            // Show error in the summary box
            vforms.displayErrorSummary(curItem, hide);
         }
         else
         {
            // Show/Hide error in a label near the control
            errLabel.style.visibility = (hide) ? "hidden" : "visible";
            // Make the label a block element if the error position is set to dynamic
            if(dType.indexOf("dyn") != -1) errLabel.style.display = (hide) ? "none" : "block";
         }

         if(!focusEvent && dType.indexOf("nofocus") == -1) curItem.focus();
      }
      else
         if(!hide && !focusEvent) vforms.displayPopup(curItem);
   },

   // Use to display error labels in each summary box
   displayErrorSummary:
   function(curItem, hide)
   {
      // Exit if the summary id's are not set
      if(vforms.summaryIDs.length <= 0) return false;

      // Check defaults
      var hide = (hide == null) ? false : hide;
      var errShown = false;

      var curSum;
      for(var i = 0; i < vforms.summaryIDs.length; i++)
      {
         curSum = document.getElementById(vforms.summaryIDs[i]);
         if(curSum == null) continue;
         
         // Indicate that the error is currently showing
         errShown = true;

         if(hide)
            curSum.style.display = "none";
         else
         {
            if(curItem != null)
            {
               curSum.innerHTML = curItem.errMsg;
               curSum.style.display = "block";
            }
         }
      }

      return errShown;
   },

   // Displays a popup error based on the field position
   displayPopup:
   function(curItem, hide)
   {
      // Check defaults
      var hide = (hide == null) ? false : hide;
      var popBox, hasPopup, displayType;
      // If we can find the popup from curItem, then do not use formParent
      if(curItem.popup)
      {
         popBox = curItem.popup; // Get popup object
         hasPopup = curItem.hasPopup; // Who has the popup?
      }
      else
      {
         popBox = curItem.formParent.popup; // Get popup object
         hasPopup = curItem.formParent.hasPopup; // Who has the popup?
      }

      // If the popup needs to be hidden, only do that. Do not set anything else
      if(hide)
      {
         popBox.style.display = "none";
         // Reset hasPopup status
         curItem.formParent.hasPopup = false;
         return;
      }

      displayType = curItem.errPos;

      // Do the focus before anything else
      if(displayType.indexOf("nofocus") == -1)
      {
         // Focus on current item.
         curItem.blockFocus = true;    // Prevent once from hiding on focus
         curItem.focus();
      }

      // If this item already has the popup showing then exit
      if(hasPopup && hasPopup == curItem) return;

      // Remove the resize event, we will be adding it later
      removeEvent(window, "resize", vforms.hidePopupsOnResize, false);

      // Get the parent top, left values (these will be our default values)
      var dLeft = getLeftPos(curItem);
      var dTop = getTopPos(curItem);
      // Get the parent height value
      var dHeight = curItem.offsetHeight;

      // Move top and move left values
      var mTop = dTop + (dHeight-vforms.popupBox[1]); // Move top down by parent height
      var mLeft = dLeft + vforms.popupArrow[2]; // Move left by preset offset

      // Set message into the popupbox and display it but keep it hidden for now
      popBox.msg.innerHTML = curItem.errMsg;
      popBox.style.visibility = "hidden";
      popBox.style.display = "block";

      // Find the full height and width of the popupbox
      // We do this after the object's display is set to block
      var boxHeight = popBox.box.offsetHeight;
      var fullHeight = boxHeight + vforms.popupArrow[1];

      // Get new X and Y positions
      var xypos = vforms.checkPopupPos(mLeft, mTop,
                                       vforms.popupBox[0], fullHeight,
                                       dLeft, (dTop - fullHeight) + vforms.popupBox[1]);

      // Find out where the arrow and message box should go within the popup
      // Do this by checking the Y value
      if(xypos[1] == mTop)
      {
         popBox.arrow.style.top = "0px";
         popBox.arrowImg.style.top = "0px";
         // Move box below arrow but remove 1px so that the arrow overlaps
         popBox.box.style.top = (vforms.popupArrow[1] - 1) + "px";
      } else {
         // Move arrow below the message box and by the extra size defined in the 3rd element of the popupArrow array
         popBox.arrow.style.top = (popBox.msg.offsetHeight + vforms.popupArrow[3]) + "px";
         // Shift the arrow image so it shows the arrow image below the box
         popBox.arrowImg.style.top = -(vforms.popupArrow[1]) + "px";

         // Move box directly above the arrow
         popBox.box.style.top = "0px";
      }

      // Display close box only if there is a noblur or nofocus set
      if(displayType.indexOf("nofocus") != -1 || displayType.indexOf("noblur") != -1)
      {
         popBox.closeBox.style.display = "block";
      }
      else
      {
         popBox.closeBox.style.display = "none";
      }

      popBox.style.visibility = "visible";   // Make it visible
      popBox.style.left = xypos[0] + "px";
      popBox.style.top = xypos[1] + "px";
      // Let the vforms object know there is a popup showing
      vforms.popupShowing = true;
      curItem.formParent.hasPopup = curItem;

      // Find the windows old width and height values
      vforms.oldWinWidth = getDocValue("Width");
      vforms.oldWinHeight = getDocValue("Height");
      // Add the resize event here
      // We set a timeout so that the popbox is given enough time to show itself
      setTimeout("addEvent(window, 'resize', vforms.hidePopupsOnResize, false)", 10);
   },
   // Checks popup position
   checkPopupPos:
   function(x, y, fwidth, fheight, defaultX, defaultY)
   {
      var docHeight = getDocTrueHeight();
      var docWidth = getDocValue("Width");

      // Get full left and top positions (8 compensates for scrollbars)
      var fullLeftPos = fwidth + x + 8;
      var fullTopPos = fheight + y + 8;

      // Check left position:
      var newLeft = (fullLeftPos > docWidth) ?
                (x - (fullLeftPos - docWidth)) : x;
      newLeft = (newLeft < defaultX) ? defaultX : newLeft;

      // Check top position:
      // If the element goes past the document height then just set it
      //    to the default Y coordinate.
      var newTop = (fullTopPos > docHeight) ? (defaultY) : y;
      // Make sure newTop  is not less than zero, if it is then just
      //    set it back to the Y coordinate
      newTop = (newTop < 0) ? y : newTop;

      return [newLeft, newTop];
   },

   // Stop all page actions
   burstBubble:
   function(e)
   {
      // Stops the submit action
      if (window.event) // Try IE Method first
      {
         window.event.cancelBubble = true;
         window.event.returnValue = false;
      }
      if (e && e.preventDefault && e.stopPropagation) // Next try DOM method
      {
         e.preventDefault();
         e.stopPropagation();
      }
      return false;  // Finally, try returning false
   },

   validByExp:
   function(strTxt, strExp)
   {
      var flag;
      var stRE = strExp;

      // First get the flag
      var re = /(\/[a-z]*)$/;
      var chkflag = re.exec(stRE);
      if (chkflag != null)
      {
         flag = stRE.substring(chkflag.index+1, stRE.length);
         stRE = stRE.replace(re,"");
      }
      // Now check strTxt with the valid expression in strExp
      re = new RegExp(stRE, flag);
      return re.test( strTxt );
   },


   /* Form events */
   blurEvent: function(e) { vforms.validateField(getObject(e), true); },

   hidePopupOnClick:
   function(e)
   {
      var curItem = getObject(e);
      if(!curItem) return; // Return if no object is found

      // Find the popup box in the parent object
      if(!curItem.formParent)
      {
         while(curItem.parentNode)
         {
            curItem = curItem.parentNode;
            if(curItem.formParent) break;
         }
      }

      if(!curItem.formParent) return false;    // Could not find popup box, return false;
      // Hide popupbox
      vforms.displayPopup(curItem, true);
   },

   // Hide popup on focus of field
   hidePopupOnFocus:
   function(e)
   {
      var curItem = getObject(e);
      if(!curItem || !vforms.popupShowing) return; // Return if no object is found

      if(curItem.blockFocus)
      {
         vforms.burstBubble(e);
         curItem.blockFocus = false;
         return;
      }

      var hasPopup = curItem.formParent.hasPopup;
      if(!hasPopup || hasPopup != curItem) return; // Return if this item does not have the popup

      var hide = true;
      vforms.displayPopup(curItem, hide);
   },

   // If the window is resized, hide the popup boxes.
   hidePopupsOnResize:
   function(e)
   {
      if(!vforms.popupShowing) return false;

      // Find the windows old width and height values
      var newWinWidth = getDocValue("Width");
      var newWinHeight = getDocValue("Height");

      // Only test the height & width values if something was set
      if( (newWinHeight && newWinWidth) &&
            (newWinHeight == vforms.oldWinHeight &&
               newWinWidth == vforms.oldWinWidth) )
                  return false;

      // Reset old height and width values
      vforms.oldWinWidth = getDocValue("Width");
      vforms.oldWinHeight = getDocValue("Height");

      for(var x = 0; x < vforms.popupList.length; x++)
         vforms.displayPopup(vforms.popupList[x], true);

      vforms.popupShowing = false;
   }
}

/* :::::::
   The following are functions required for vforms to function propertly
:::::::::: */

// Returns and identifying value for an object passed by event.
var getObject =
   function(event) {
     // Object detection
     if (event.srcElement) {
       return event.srcElement;
     } else if (event.target) {
       return event.target;
     } else {
       return;
     }
   };

// Returns the document height or width
var getDocValue =
   function(valHW)
   {
      // If window.innerHeight/Width is provided, which is fully trustworthy, use that.
      // Else if document.documentElement.clientHeight/Width is provided and either one is greater than 0, use that. 
      // Else if document.body.clientHeight/Width is provided, use that.
      // Else return false.

      var newVal;
      newVal = (window["inner" + valHW]) ? window["inner" + valHW] :
                  (document.documentElement) ?
                     document.documentElement["client" + valHW] : 0;
      return (newVal > 0) ? newVal :
                  (document.body) ? document.body["client" + valHW] : false;
   };

// Returns the value of the document element based on valSC
// IE: clientHeight, clientWidth, 
//     scrollHeight, scrollWidth, scrollLeft, scrollTop,
//     offsetHeight, offsetWidth
var getDocElementValue = 
   function(valSC)
   {
      return (document.documentElement) ? document.documentElement[valSC] :
            document.body[valSC];
   };

// This returns the height of the inner window.. it does not return scrollheight values
var getDocTrueHeight =
   function()
   {
      var dcHeight = getDocElementValue("clientHeight");   // Document HEIGHT value
      // Make sure the body height is not too big
      // We want the smallest value between documentElement and body values (IE is to blame)
      if(document.body && (dcHeight < 1 || dcHeight > document.body["clientHeight"]))
         // document.body method is smaller so we use that
         dcHeight = document.body["clientHeight"];
      return dcHeight;  // This is the closets value for all browsers
   };

// Returns an objects true x and y positions
var getObjectXY =
function(obj)
{
	var curleft = curtop = 0;
	if (obj.offsetParent)
	{
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
};
var getLeftPos = function(obj) { return getObjectXY(obj)[0]; };
var getTopPos = function(obj) { return getObjectXY(obj)[1]; };

// Adds an event to an object. Such as click, or mouseover
var addEvent;
   if(document.addEventListener)
      addEvent =
         function(obj, evType, fn, useCapture) {
            obj.addEventListener(evType, fn, useCapture);
         };
   else
      addEvent =
         function(obj, evType, fn, useCapture) {
            obj.attachEvent("on" + evType, fn);
         };


// Removes an event from an object. Such as click, or mouseover
var removeEvent;
   if(document.addEventListener)
      removeEvent =
         function(obj, evType, fn, useCapture) {
            obj.removeEventListener(evType, fn, useCapture);
         };
   else
      removeEvent =
         function(obj, evType, fn, useCapture) {
            obj.detachEvent("on" + evType, fn);
         };
/* ::::::: Required Functions end here :::::::::::: */

addEvent(window, "load", vforms.setupForms, false);

// -->