/***

    wForms 2.0
    a javascript extension to web forms. 

    Build $Tue, 20 Mar 2007 15:17:28 UTC$

    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
    diff against the source tree, not this file.

    Copyright (c) 2005-2007 Cedric Savarese <cedric@veerwest.com> and contributors.
    This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
    For more information, visit: http://www.formassembly.com/wForms 

    Build script by Troels Knak-Nielsen <troelskn@gmail.com>

***/

// wForms - a javascript extension to web forms.
// see http://www.formassembly.com/wForms
// This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>

function wHELPERS() {};

// addEvent adapated from http://ejohn.org/projects/flexible-javascript-events/
// and  Andy Smith's (http://weblogs.asp.net/asmith/archive/2003/10/06/30744.aspx)
wHELPERS.prototype.addEvent = function(obj, type, fn) {
  if(!obj) { return; }
  
  if (obj.attachEvent) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else if(obj.addEventListener) {      
    obj.addEventListener( type,fn, false );
  } else {
    var originalHandler = obj["on" + type]; 
    if (originalHandler) { 
      obj["on" + type] = function(e){originalHandler(e);fn(e);}; 
    } else { 
      obj["on" + type] = fn; 
    } 
  }
}

wHELPERS.prototype.removeEvent = function(obj, type, fn) {
  if (obj.detachEvent) {
    if(obj[type+fn]) {
      obj.detachEvent( 'on'+type, obj[type+fn] );
      obj[type+fn] = null;
    }
  } else if(obj.removeEventListener)
    obj.removeEventListener( type, fn, false );
  else {
    obj["on" + type] = null;
  }
}

// Returns the event's source element 
wHELPERS.prototype.getSourceElement = function(e) {  
  if(!e) e = window.event;  
  if(e.target)
    var srcE = e.target;
  else
    var srcE = e.srcElement;
  if(!srcE) return null;
  if(srcE.nodeType == 3) srcE = srcE.parentNode; // safari weirdness    
  if(srcE.tagName.toUpperCase()=='LABEL' && e.type=='click') { 
    // when clicking a label, firefox fires the input onclick event
    // but the label remains the source of the event. In Opera and IE 
    // the source of the event is the input element. Which is the 
    // expected behavior, I suppose.    
    if(srcE.getAttribute('for')) {
      srcE = document.getElementById(srcE.getAttribute('for'));
    }
  }
  return srcE;
}

// Cancel the default execution of an event.
wHELPERS.prototype.preventEvent = function(e) {
  if (!e) e = window.event;
  if (e.preventDefault) e.preventDefault();
  else e.returnValue = false;
  return false;
}

// Cancel the propagation of the event
wHELPERS.prototype.stopPropagation = function(e) {
  if (!e) var e = window.event;
  e.cancelBubble = true;
  if (e.stopPropagation) e.stopPropagation();
}

// Generates a random ID
wHELPERS.prototype.randomId = function () {
  var seed = (new Date()).getTime();
  seed = seed.toString().substr(6);
  for (var i=0; i<6;i++)
    seed += String.fromCharCode(48 + Math.floor((Math.random()*10)));
  return "id-" + seed;
}

// Activating an Alternate Stylesheet (thx to: http://www.howtocreate.co.uk/tutorials/index.php?tut=0&part=27)
// Use this to activate a CSS Stylesheet that shouldn't be used if javascript is turned off.
// The stylesheet rel attribute should be 'alternate stylesheet'. The title attribute MUST be set.
wHELPERS.prototype.activateStylesheet = function(sheetref) {
  if(document.getElementsByTagName) {
    var ss=document.getElementsByTagName('link');
  } else if (document.styleSheets) {
    var ss = document.styleSheets;
  }
  for(var i=0;ss[i];i++ ) {
    if(ss[i].href.indexOf(sheetref) != -1) {
      ss[i].disabled = true;
      ss[i].disabled = false;      
    }
  }
}

// hasClass
wHELPERS.prototype.hasClass = function(element,className) {
  if(element && element.className) {
    if((' ' + element.className + ' ').indexOf(' ' + className +' ') != -1) {
      return true;
    }
  }
  return false;
}
wHELPERS.prototype.hasClassPrefix = function(element,className) {
  if(element && element.className) {
    if((' ' + element.className).indexOf(' ' + className) != -1) {
      return true;
    }
  }
  return false;
}
  wHELPERS.prototype.hasIdPrefix = function(element,idPrefix) {
    if(element && element.id) {
      if(element.id.indexOf(idPrefix) != -1) {
        return true;
      }
    }
    return false;
  }


// getTop / getLeft  
// Returns pixel coordinates from the top-left window corner.
wHELPERS.prototype.getTop = function(obj) {
  var cur = 0;
  if(obj.offsetParent) {    
    while(obj.offsetParent) {
      if((new wHELPERS()).getComputedStyle(obj,'position') == 'relative' ) {
        // relatively postioned element
        return cur;
      }
      cur+=obj.offsetTop;
      obj = obj.offsetParent;
    }
  }
  return cur;
}
wHELPERS.prototype.getLeft = function(obj) {
  var cur = 0;
  if(obj.offsetParent) {    
    while(obj.offsetParent) {
      if((new wHELPERS()).getComputedStyle(obj,'position') == 'relative' ) {
        // relatively postioned element
        return cur;
      }
      if((new wHELPERS()).getComputedStyle(obj,'position') == 'absolute' ) {
        // relatively postioned element
        return cur;
      }
      cur+=obj.offsetLeft;
      obj = obj.offsetParent;
    }
  }
  return cur;
}

wHELPERS.prototype.getComputedStyle = function(element, styleName) {
  if(window.getComputedStyle) {
    return window.getComputedStyle(element,"").getPropertyValue(styleName);
  } else if(element.currentStyle) {  
    return element.currentStyle[styleName];
  }
  return false;
}
// backward compatibility
  var wHelpers = wHELPERS;   


   /* 
  * MISC FUNCTIONS 
   /* ------------------------------------------------------------------------------------------ */

// Push implementation for IE5/mac
if (!Array.prototype.push) { 
  Array.prototype.push = function() { 
    for (var i = 0; i < arguments.length; ++i) { 
      this[this.length] = arguments[i]; 
    } 
    return this.length; 
  }; 
}


  if(wHELPERS) {
    var wFORMS = { 
    
    debugLevel     : 0, /* 0: Inactive, 1+: Debug Level */
    
    helpers        : new wHELPERS(),     
    behaviors      : {},
    onLoadComplete : new Array(),  /* stack of functions to call once all behaviors have been applied */
    processedForm  : null,
    
    onLoadHandler  : function() {
      for(var behaviorName in  wFORMS.behaviors) {
         wFORMS.debug('wForms/loaded behavior: ' + behaviorName);
      }
     
      for (var i=0;i<document.forms.length;i++) {
        wFORMS.debug('wForms/initialize: '+ (document.forms[i].name || document.forms[i].id) );
        wFORMS.addBehaviors(document.forms[i]);
      }
    },
    
    addBehaviors : function (node) {
    if(!node) return;
    
    if(!node.nodeType) {
      // argument is not a node. probably an id string. 
      // (typeof not used for IE5/mac compatibility)
      node = document.getElementById(node);
    }
    if(!node || node.nodeType!=1) return;
    
    deep=(arguments.length>1)?arguments[1]:true;  

    wFORMS._addBehaviors(node, deep);          
    },
      
    _addBehaviors : function (node, deep) {
     if(node.getAttribute('rel')=='no-behavior') {
        return false;
     }
     // Process element nodes only
     if(node.nodeType == 1) { 
        if(node.tagName == 'FORM') {
          wFORMS.processedForm = node;
        }      
        for(var behaviorName in wFORMS.behaviors) {
          wFORMS.behaviors[behaviorName].evaluate(node);
        }      
        if(deep) {
          for (var i=0, cn=node.childNodes, l=cn.length; i<l; i++) {
             if(cn[i].nodeType==1)
             wFORMS._addBehaviors(cn[i], deep);
          }
        }        
        if(node.tagName == 'FORM') {
          // run the init stack
          for (var i=0;i<wFORMS.onLoadComplete.length;i++) {
            wFORMS.onLoadComplete[i].func(wFORMS.onLoadComplete[i].form);
          }
          // empty the stack            
          if(wFORMS.onLoadComplete.length > 0) {
            wFORMS.onLoadComplete = new Array();
          }
        }
      }
    },
    
    hasBehavior: function(behaviorName) {
      if(wFORMS.behaviors[behaviorName]) return true;
      return false;
    },
    
    /* 
     * DEBUG FUNCTIONS 
     * ------------------------------------------------------------------------------------------ */
    debug : function(txt) { 
    msgLevel = arguments[1] || 10;   // 1 = least importance, X = most important
    
    if(wFORMS.debugLevel > 0 && msgLevel >= wFORMS.debugLevel) {
      if(!wFORMS.debugOutput)
        wFORMS.initDebug();
      if(wFORMS.debugOutput)
        wFORMS.debugOutput.innerHTML += "<br />" + txt;
    }
    },
    
    initDebug : function() {
    var output = document.getElementById('debugOutput');
    if(!output) {
      output = document.createElement('div');
      output.id = 'debugOutput';
      output.style.position   = 'absolute';
      output.style.right      = '10px';
      output.style.top        = '10px';
      output.style.zIndex     = '300';
      output.style.fontSize   = 'x-small';
      output.style.fontFamily = 'courier';
      output.style.backgroundColor = '#DDD';
      output.style.padding    = '5px';
      if(document.body) // if page fully loaded
        wFORMS.debugOutput = document.body.appendChild(output);
    }
    if(wFORMS.debugOutput)
      wFORMS.debugOutput.ondblclick = function() { this.innerHTML = '' };
  }
  };
  
  wFORMS.NAME     = "wForms";
  wFORMS.VERSION  = "2.0";
  wFORMS.__repr__ = function () {
  return "[" + this.NAME + " " + this.VERSION + "]";
  };
  wFORMS.toString = function () {
  return this.__repr__();
  };
 
 
  // For backward compatibility
  wFORMS.utilities = wFORMS.helpers;
  var wf           = wFORMS; 
  wf.utilities.getSrcElement        = wFORMS.helpers.getSourceElement;
  wf.utilities.XBrowserPreventEventDefault  = wFORMS.helpers.preventEvent;
  
  // Initializations:
  
  // Attach JS only stylesheet.
  wFORMS.helpers.activateStylesheet('wforms-jsonly.css');
  // Parse document and apply wForms behavior
  wFORMS.helpers.addEvent(window,'load',wFORMS.onLoadHandler);
  } 


// ------------------------------------------------------------------------------------------
// Field Hint / Tooltip Behavior
// ------------------------------------------------------------------------------------------
  
if(wFORMS) {

       // Component properties 
       wFORMS.idSuffix_fieldHint           = "-H";                     // a hint id is the associated field id (or name) plus this suffix
       wFORMS.className_inactiveFieldHint  = "field-hint-inactive";    // visual effect depends on CSS stylesheet
       wFORMS.className_activeFieldHint    = "field-hint";             // visual effect depends on CSS stylesheet
       
       
       wFORMS.behaviors['hint'] = {
           name: 'hint', 
           
       // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate
             evaluate: function(node) {
               if(node.id) {
                    if(node.id.indexOf(wFORMS.idSuffix_fieldHint)>0) {                    
                      // this looks like a field-hint. See if we have a matching field.                     
                      // try first with the id, then with the name attribute.
                      var id     = node.id.replace(wFORMS.idSuffix_fieldHint, '');                      
                      var hinted = document.getElementById(id) || wFORMS.processedForm[id];
                    } 
                   if(hinted) {
             // is hint placed on a radio group using the name attribute?
             if(hinted.length > 0 && hinted[0].type=='radio') {
               var hintedGroup = hinted;
               l = hinted.length;
             } else {
               var hintedGroup = new Array(hinted);
               l = 1;
             }
             
             for(var i=0;i<l;i++) {
               hinted = hintedGroup[i];

               wFORMS.debug('hint/evaluate: '+ (node.id || node.name));
               switch(hinted.tagName.toUpperCase()) {
                 case 'SELECT': 
                 case 'TEXTAREA':               
                 case 'INPUT':
                  wFORMS.helpers.addEvent(hinted,'focus',wFORMS.behaviors['hint'].run);
                  wFORMS.helpers.addEvent(hinted,'blur' ,wFORMS.behaviors['hint'].remove);
                  break;
                 default:
                  wFORMS.helpers.addEvent(hinted,'mouseover',wFORMS.behaviors['hint'].run);
                  wFORMS.helpers.addEvent(hinted,'mouseout' ,wFORMS.behaviors['hint'].remove);
                  break;
               }
               
             }
                   } 
               }
           },

       
           // run: executed when the behavior is activated
           run: function(e) {
               var element   = wFORMS.helpers.getSourceElement(e);
               var fieldHint = document.getElementById(element.id   + wFORMS.idSuffix_fieldHint);
               if(!fieldHint) // try again with the element's name attribute
                   fieldHint = document.getElementById(element.name + wFORMS.idSuffix_fieldHint);
               if(fieldHint) {
                   fieldHint.className = fieldHint.className.replace(wFORMS.className_inactiveFieldHint,
                                                                     wFORMS.className_activeFieldHint);
           // Field Hint Absolute Positionning
           fieldHint.style.top  =  (wFORMS.helpers.getTop(element)+ element.offsetHeight).toString() + "px";
           if(element.tagName.toUpperCase() == 'SELECT') 
             fieldHint.style.left =  (wFORMS.helpers.getLeft(element) + (element.offsetWidth- 8)).toString() + "px";
           else 
             fieldHint.style.left =  (wFORMS.helpers.getLeft(element)).toString() + "px"; /* + element.offsetWidth */
//           wFORMS.debug('hint/run: ' + (element.id || element.name) , 5);           
         }
           },
       
           // remove: executed if the behavior should not be applied anymore
           remove: function(e) {
               var element   = wFORMS.helpers.getSourceElement(e);
               var fieldHint = document.getElementById(element.id   + wFORMS.idSuffix_fieldHint);
               if(!fieldHint) // try again with the element's name attribute
                   fieldHint = document.getElementById(element.name + wFORMS.idSuffix_fieldHint);
               if(fieldHint)
                   fieldHint.className = fieldHint.className.replace(wFORMS.className_activeFieldHint,
                                                                     wFORMS.className_inactiveFieldHint);
//         wFORMS.debug('hint/remove: ' + (element.id || element.name) , 5);           
           }
       }
   }
// ------------------------------------------------------------------------------------------
// Form Paging Behavior
// ------------------------------------------------------------------------------------------
  
   if(wFORMS) {
    // Component properties 
    wFORMS.className_paging        = "wfPage";
    wFORMS.className_pagingCurrent    = "wfCurrentPage";
    wFORMS.className_pagingButtons    = "wfPageButton";
    wFORMS.className_hideSubmit      = "wfHideSubmit";
    wFORMS.idPrefix_pageIndex      = "wfPgIndex-";
    wFORMS.runValidationOnPageNext     = true;
    
    if(!wFORMS.arrMsg) wFORMS.arrMsg   = new Array();
    wFORMS.arrMsg[4]           = "Next Page";      //arrMsg[4] for backward compatibility
    wFORMS.arrMsg[5]           = "Previous Page";  //arrMsg[5] for backward compatibility


    wFORMS.behaviors['paging'] = {

      idSuffix_buttonsPlaceholder: "-buttons",
      className_pageNextButton: wFORMS.className_pagingButtons + " wfPageNextButton",
      className_pagePreviousButton: wFORMS.className_pagingButtons + " wfPagePreviousButton",      
      behaviorInUse : false,
      allowNestedPages: false,
      onPageChange : null, /* Function to run when the page is changed */

      // ------------------------------------------------------------------------------------------
      // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate
      // ------------------------------------------------------------------------------------------
      evaluate: function(node) {
        if (wFORMS.helpers.hasClass(node,wFORMS.className_paging)) {
          
          if(!wFORMS.behaviors['paging'].allowNestedPages && wFORMS.behaviors['paging'].getPageElement(node)) {
            // found a parent node that is also a page element. 
            // remove paging class so that the content is not hidden.
            node.className = node.className.replace(wFORMS.className_paging,"");
            return;
          }
            
          wFORMS.behaviors['paging'].behaviorInUse = true;
          
          var currentPageIndex = wFORMS.behaviors['paging'].getPageIndex(node);
          if(currentPageIndex > 1) {
            // add previous page button  
            var placeholder = this.getButtonPlaceholder(node);
            var button = placeholder.insertBefore(this.createPreviousPageButton(),placeholder.firstChild);            
            wFORMS.helpers.addEvent(button,'click',wFORMS.behaviors['paging'].pagingPrevious);            
          } else {
            // set current page class
            node.className += ' ' + wFORMS.className_pagingCurrent;
            
            // get the corresponding form element
            var form = wFORMS.behaviors['paging'].getFormElement(node);  
                                                  
            // prevent submission of form with enter key.
            wFORMS.helpers.addEvent(form,'submit', function(e) { var element = wFORMS.helpers.getSourceElement(e);
                                       if(element.type && element.type.toLowerCase()=='text') 
                                        return wFORMS.preventEvent(e); } );
            wFORMS.preventSubmissionOnEnter = true; // for input validation behavior
            
          }
          if(document.getElementById(wFORMS.idPrefix_pageIndex+(currentPageIndex+1).toString())) {
            // add next page button  
            var placeholder = this.getButtonPlaceholder(node);
            var button = placeholder.appendChild(this.createNextPageButton());
            wFORMS.helpers.addEvent(button,'click',wFORMS.behaviors['paging'].pagingNext);  
            // hide submit button until the last page of the form is reached (do it once on the 1st page)
            if(currentPageIndex==1) {              
              wFORMS.behaviors['paging'].hideSubmitButton(form);
            }            
          }
        }
        
      },
      getButtonPlaceholder: function(page) {
        var p = document.getElementById(page.id+this.idSuffix_buttonsPlaceholder);
        if(!p) {
          var buttonPlaceholder = document.createElement("div");   
          buttonPlaceholder = page.appendChild(buttonPlaceholder);  
          buttonPlaceholder.className = 'actions';
          buttonPlaceholder.id = page.id+this.idSuffix_buttonsPlaceholder;
          return buttonPlaceholder;
        }        
        return p; 
      },
      createNextPageButton: function() {            
        var button = document.createElement("input"); 
        button.setAttribute('value',wFORMS.arrMsg[4]);  
        button.setAttribute('type',"button");  
        button.className = this.className_pageNextButton;
        return button;
      },
      createPreviousPageButton: function() {
        // add previous page button      
        var button = document.createElement("input"); 
        button.setAttribute('value',wFORMS.arrMsg[5]);  
        button.setAttribute('type',"button");  
        button.className = this.className_pagePreviousButton;
        return button;
      },
            
      // ------------------------------------------------------------------------------------------
      // pagingNext
      // ------------------------------------------------------------------------------------------
      pagingNext: function(e) {
        var element  = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e
        
        var pageElement     = wFORMS.behaviors['paging'].getPageElement(element);
        var pageIndex       = wFORMS.behaviors['paging'].getPageIndex(pageElement) + 1;
        var nextPageElement = document.getElementById(wFORMS.idPrefix_pageIndex+pageIndex.toString());
        
        if(nextPageElement) {
          if(!wFORMS.hasBehavior('validation') ||
             (wFORMS.hasBehavior('validation') && !wFORMS.runValidationOnPageNext) || 
             (wFORMS.hasBehavior('validation') &&  wFORMS.runValidationOnPageNext && wFORMS.functionName_formValidation(e, true))) {
            
            pageElement.className      = pageElement.className.replace(new RegExp(wFORMS.className_pagingCurrent,"g"),"");
            nextPageElement.className += ' ' + wFORMS.className_pagingCurrent;

            // show submit button if the last page of the form is reached
            if(wFORMS.behaviors['paging'].isLastPage(pageIndex)) {
              var form = wFORMS.behaviors['paging'].getFormElement(nextPageElement);
              wFORMS.behaviors['paging'].showSubmitButton(form);
            }
            // trigger onPageChange event            
            if(wFORMS.behaviors['paging'].onPageChange) {
              wFORMS.behaviors['paging'].onPageChange(nextPageElement);
            }
            window.scroll(0,0);
          }          
        }
      },
      
      // ------------------------------------------------------------------------------------------
      // pagingPrevious
      // ------------------------------------------------------------------------------------------        
      pagingPrevious: function(e) {
        var element  = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e
 
        var pageElement         = wFORMS.behaviors['paging'].getPageElement(element);
        var pageIndex           = wFORMS.behaviors['paging'].getPageIndex(pageElement) - 1;
        var previousPageElement = document.getElementById(wFORMS.idPrefix_pageIndex+pageIndex.toString());

        if(previousPageElement) {
          pageElement.className          = pageElement.className.replace(new RegExp(wFORMS.className_pagingCurrent,"g"),"");
          previousPageElement.className += ' ' + wFORMS.className_pagingCurrent;                    
                              
          // hide submit button 
          var form = wFORMS.behaviors['paging'].getFormElement(previousPageElement);          
          wFORMS.behaviors['paging'].hideSubmitButton(form);
          
          // trigger onPageChange event
          if(wFORMS.behaviors['paging'].onPageChange) {
            wFORMS.behaviors['paging'].onPageChange(previousPageElement);
          }
          window.scroll(0,0);
        }
      },
      // ------------------------------------------------------------------------------------------
      // show/hide submit button
      // ------------------------------------------------------------------------------------------                
      showSubmitButton: function(form) {
        var buttons = form.getElementsByTagName('input');
        for (var i=0;i<buttons.length;i++) {
          if(buttons[i].type && buttons[i].type.toLowerCase() == 'submit') {
            buttons[i].className = buttons[i].className.replace(wFORMS.className_hideSubmit,"");
          }
        }
      },
      hideSubmitButton: function(form) {
        var buttons = form.getElementsByTagName('input');
        for (var i=0;i<buttons.length;i++) {
          if(buttons[i].type && buttons[i].type.toLowerCase() == 'submit' 
               && !wFORMS.helpers.hasClass(buttons[i],wFORMS.className_hideSubmit) ) {
            buttons[i].className += ' ' + wFORMS.className_hideSubmit; 
          }
        }
      },
      
      // ------------------------------------------------------------------------------------------
      // isLastPage
      // ------------------------------------------------------------------------------------------          
      isLastPage: function(pageIndex) {
        if(isNaN(pageIndex)) {
          pageIndex = parseInt(pageIndex.replace(/[\D]*/,""));
        }
        pageIndex++;
        var furtherPageElement = document.getElementById(wFORMS.idPrefix_pageIndex+pageIndex.toString());      
        if(!furtherPageElement) 
          return true;
        return false;
      },
      // ------------------------------------------------------------------------------------------
      // gotoPage
      // ------------------------------------------------------------------------------------------        
      gotoPage: function(pageIndex) { 
        
        if(isNaN(pageIndex)) {
          var pageElement = document.getElementById(pageIndex);          
        } else {
          var pageElement = document.getElementById(wFORMS.idPrefix_pageIndex+pageIndex.toString());
        }        
        if(!pageElement) return false;
        
        // get the corresponding form element
        var form = wFORMS.behaviors['paging'].getFormElement(pageElement);
        
        // hide current page
        var allElements = form.getElementsByTagName("*");
        for(var i=0; i< allElements.length; i++) {
          var n =  allElements[i];          
          if(wFORMS.helpers.hasClass(allElements[i],wFORMS.className_pagingCurrent)) {            
            n.className = n.className.replace(new RegExp(wFORMS.className_pagingCurrent,"g"),"");  
            break;
          }
        }
        //show/hide submit button as necessary
        
        if(wFORMS.behaviors['paging'].isLastPage(pageIndex)) 
          wFORMS.behaviors['paging'].showSubmitButton(form);
        else { 
          wFORMS.behaviors['paging'].hideSubmitButton(form);
        }
        // Show the page
        pageElement.className += ' ' + wFORMS.className_pagingCurrent;
        
        // trigger onPageChange event
        if(wFORMS.behaviors['paging'].onPageChange) {
          wFORMS.behaviors['paging'].onPageChange(pageElement);
        }
      },
      // ------------------------------------------------------------------------------------------
      // getFormElement
      // ------------------------------------------------------------------------------------------              
      getFormElement: function(element) {
        var form = element.parentNode;
        while(form && form.tagName != "FORM")
          form = form.parentNode;
        return form;
      },
      // ------------------------------------------------------------------------------------------
      // getPageElement
      // ------------------------------------------------------------------------------------------              
      getPageElement: function(element) {
        var n = element.parentNode;
        while(n && n.tagName != "FORM" && (!n.className || !wFORMS.helpers.hasClass(n,wFORMS.className_paging)))
          n = n.parentNode;
        if(n && wFORMS.helpers.hasClass(n,wFORMS.className_paging))
          return n;
        else
          return null;
      },
      // ------------------------------------------------------------------------------------------
      // getPageIndex
      // ------------------------------------------------------------------------------------------                  
      getPageIndex: function(element) {
        if(element && element.id) 
          return parseInt(element.id.replace(/[\D]*/,""));
        else
          return null;
      }
       } // End wFORMS.behaviors['paging']
   }
   
   
   
// ------------------------------------------------------------------------------------------
// Repeat Behavior
// ------------------------------------------------------------------------------------------
      
   if(wFORMS) {
    // Component properties 
    wFORMS.className_repeat       = "repeat";
    wFORMS.className_delete       = "removeable";
    wFORMS.className_duplicateLink     = "duplicateLink";
    wFORMS.className_removeLink     = "removeLink";
    wFORMS.className_preserveRadioName  = "preserveRadioName";    
    wFORMS.idSuffix_repeatCounter    = "-RC";
    wFORMS.idSuffix_duplicateLink    = "-wfDL";                   
    wFORMS.preserveRadioName      = false;                   // if true, Repeat behavior will preserve name attributes for radio input. 
    wFORMS.limitSwitchScope        = true;                      // if true, Repeat behavior will limit the scope of nested switches.
    
    if(!wFORMS.arrMsg) wFORMS.arrMsg   = new Array();
    wFORMS.arrMsg[0]           = "Add another response";            // repeat link
    wFORMS.arrMsg[1]           = "Will duplicate this question or section." // title attribute on the repeat link 
    wFORMS.arrMsg[2]           = "Remove";                  // remove link
    wFORMS.arrMsg[3]           = "Will remove this question or section."    // title attribute on the remove link
    
    wFORMS.behaviors['repeat'] = {
      
      onRepeat: null, /* Function to run after the element is repeated */
      onRemove: null,   /* Function to run after the element is removed  */
      allowRepeat: null, /* Function for fine control on repeatable section */
      
         // ------------------------------------------------------------------------------------------
         // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate
         // ------------------------------------------------------------------------------------------
      evaluate: function(node) {
        
        // Repeatable element
        if(wFORMS.helpers.hasClass(node, wFORMS.className_repeat)) {
          //wFORMS.debug('evaluate/repeat: '+ node.id,3);
           
           if(!node.id) 
            node.id = wFORMS.helpers.randomId();
            
          // Check if we have a 'repeat' link
          var repeatLink = document.getElementById(node.id + wFORMS.idSuffix_duplicateLink);
          if(!repeatLink) {        
            // create the repeat link
            repeatLink = wFORMS.behaviors['repeat'].createRepeatLink(node.id);
                        
            // find where to insert the link
            if(node.tagName.toUpperCase()=="TR") {
              // find the last TD
              var n = node.lastChild;  
              while(n && n.nodeType != 1)  
                n = n.previousSibling;
              if(n && n.nodeType == 1) 
                n.appendChild(repeatLink);
              // Else Couldn't find the TD. Table row malformed ?
            } else
              node.appendChild(repeatLink);
          }
          // Add hidden counter field if necessary
          var counterField = document.getElementById(node.id + wFORMS.idSuffix_repeatCounter);
          if(!counterField) {
            // IE Specific :-(
            if(document.all && !window.opera) { 
              // see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
              var counterFieldId = node.id + wFORMS.idSuffix_repeatCounter;
              if(navigator.appVersion.indexOf("MSIE") != -1 && navigator.appVersion.indexOf("Windows") == -1) // IE5 Mac
                counterField   = document.createElement("INPUT NAME=\"" + counterFieldId + "\"");
              else
                counterField   = document.createElement("<INPUT NAME=\"" + counterFieldId + "\"></INPUT>");           
              counterField.type  ='hidden';
              counterField.id    = counterFieldId; 
              counterField.value = "1";
            }
            else {
              counterField = document.createElement("INPUT"); 
              counterField.setAttribute('type','hidden'); // hidden
              counterField.setAttribute('value','1');
              counterField.setAttribute('name', node.id + wFORMS.idSuffix_repeatCounter);
              counterField.setAttribute('id', node.id + wFORMS.idSuffix_repeatCounter); 
            }
            
            // get the form element            
            var form = node.parentNode;
            while(form && form.tagName.toUpperCase() != "FORM")
              form = form.parentNode;
            
            form.appendChild(counterField);
          }
          
          // Add event handler      
          wFORMS.helpers.addEvent(repeatLink,'click',wFORMS.behaviors['repeat'].duplicateFieldGroup);      
        }  
           // ------------------------------------------------------------------------------------------
        // Removeable element
        if(wFORMS.helpers.hasClass(node, wFORMS.className_delete)) {
          var removeLink = wFORMS.behaviors['repeat'].createRemoveLink();
          // find where to insert the link
          if(node.tagName.toUpperCase()=="TR") {
            // find the last TD
            var n = node.lastChild;  
            while(n && n.nodeType != 1)  
              n = n.previousSibling;
            if(n && n.nodeType == 1) 
              n.appendChild(removeLink);
            // Else Couldn't find the TD. Table row malformed ?
          } else
            node.appendChild(removeLink);
        }  
             },
      createRepeatLink: function(id) {
        var repeatLink = document.createElement("a"); 
        var spanNode = document.createElement("span");  // could be used for CSS image replacement 
        var textNode = document.createTextNode(wFORMS.arrMsg[0]);
        repeatLink.id = id + wFORMS.idSuffix_duplicateLink;  
        repeatLink.setAttribute('href',"#");  
        repeatLink.className = wFORMS.className_duplicateLink;      
        repeatLink.setAttribute('title', wFORMS.arrMsg[1]);  
        spanNode.appendChild(textNode); 
        repeatLink.appendChild(spanNode); 
        return repeatLink;
      },
      createRemoveLink: function() {
        var removeLink = document.createElement("a");
        var spanNode   = document.createElement("span");  // could be used for CSS image replacement 
        var textNode   = document.createTextNode(wFORMS.arrMsg[2]);
        removeLink.setAttribute('href',"#");  
        removeLink.className = wFORMS.className_removeLink;
        removeLink.setAttribute('title',wFORMS.arrMsg[3]);  
        spanNode.appendChild(textNode); 
        removeLink.appendChild(spanNode);
        wFORMS.helpers.addEvent(removeLink,'click',wFORMS.behaviors['repeat'].removeFieldGroup);
        return removeLink;
      },
         duplicateFieldGroup: function(e) {
                 
        var element  = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e
        
        // override of the wFORMS.preserveRadioName property using a class on the repeat link.
        var preserveRadioName = wFORMS.helpers.hasClass(element,wFORMS.className_preserveRadioName) ? true : wFORMS.preserveRadioName;
        //wFORMS.debug('preserveRadioName='+preserveRadioName);
        
        // Get Element to duplicate.        
        while (element && !wFORMS.helpers.hasClass(element,wFORMS.className_duplicateLink)) {
          element = element.parentNode;
        }  
        var idOfRepeatedSection = element.id.replace(wFORMS.idSuffix_duplicateLink,"");
        var element = document.getElementById(idOfRepeatedSection); 
        
        
        if (element) {
          var wBehavior = wFORMS.behaviors['repeat']; // shortcut
          
          // Check if we have a custom function that prevents the repeat
          if(wBehavior.allowRepeat) {            
            if(!wBehavior.allowRepeat(element)) return false;
          }
          
          // Extract row counter information
          counterField = document.getElementById(element.id + wFORMS.idSuffix_repeatCounter);
          if(!counterField) return; // should not happen.
          var rowCount = parseInt(counterField.value) + 1;
          // Prepare id suffix
          var suffix = "-" + rowCount.toString()
          // duplicate node tree 
          var dupTree = wBehavior.replicateTree(element, null, suffix, preserveRadioName);  //  sourceNode.cloneNode(true); 
          // find insert point in DOM tree (after existing repeated element)
          var insertNode = element.nextSibling;
          
          while(insertNode && 
             (insertNode.nodeType==3 ||       // skip text-node that can be generated server-side when populating a previously repeated group 
              wFORMS.helpers.hasClass(insertNode,wFORMS.className_delete))) {            
            insertNode = insertNode.nextSibling;
          }
          element.parentNode.insertBefore(dupTree,insertNode);   // Buggy rendering in IE5/Mac
          // if(navigator.appVersion.indexOf("MSIE") != -1 && navigator.appVersion.indexOf("Windows") == -1)      
          //
          
          // the copy is not duplicable, it's removeable
          dupTree.className = element.className.replace(wFORMS.className_repeat,wFORMS.className_delete);
          // Save new row count       
          document.getElementById(element.id + wFORMS.idSuffix_repeatCounter).value = rowCount;
          // re-add wFORMS behaviors
          wFORMS.addBehaviors(dupTree);
          
          if(wBehavior.onRepeat)
            wBehavior.onRepeat(element,dupTree);
        }        
        
        return wFORMS.helpers.preventEvent(e);
      },
      
         removeFieldGroup: function(e) { 
        var element  = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e
        // Get Element to remove.
        var element = element.parentNode;
        while (element && !wFORMS.helpers.hasClass(element,wFORMS.className_delete)) {
          element = element.parentNode;
        }  
        element.parentNode.removeChild(element);
        if(wFORMS.behaviors['repeat'].onRemove)
            wFORMS.behaviors['repeat'].onRemove(element);
        return wFORMS.helpers.preventEvent(e);
      },  
      
      removeRepeatCountSuffix: function(str) {
        return str.replace(/-\d+$/,'');
      },
  
      replicateTree: function(element,parentElement, idSuffix, preserveRadioName) {
        
        // Duplicating TEXT-NODE (do not copy value of textareas)
        if(element.nodeType==3) { 
          if(element.parentNode.tagName.toUpperCase() != 'TEXTAREA')
            var newElement = document.createTextNode(element.data); 
        } 
        // Duplicating ELEMENT-NODE
        else if(element.nodeType==1) { 
          
          // Do not copy repeat/remove links
          if(wFORMS.helpers.hasClass(element,wFORMS.className_duplicateLink) ||
             wFORMS.helpers.hasClass(element,wFORMS.className_removeLink))               
            return null; 
          // Exclude duplicated elements of a nested repeat group
          if(wFORMS.helpers.hasClass(element,wFORMS.className_delete)) 
            return null; 
          // Adjust row suffix id if we find a nested repeat group 
          if(wFORMS.helpers.hasClass(element,wFORMS.className_repeat) && parentElement!=null)
            idSuffix = idSuffix.replace('-','__');
          
          if(!document.all || window.opera) { 
            // Common Branch
            var newElement = document.createElement(element.tagName); 
          } else {
            // IE Branch 
            // see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp            
            var tagHtml = element.tagName;
            
            if(element.name)           
              if (element.tagName.toUpperCase() == "INPUT" && 
                element.type.toLowerCase()    == "radio" && preserveRadioName)
                tagHtml += " NAME='" + element.name + "' ";
              else
                tagHtml += " NAME='" + wFORMS.behaviors['repeat'].removeRepeatCountSuffix(element.name) + idSuffix + "' ";
            if(element.type) {
              tagHtml += " TYPE='" + element.type + "' ";
            }
            if(element.selected) 
              tagHtml += " SELECTED='SELECTED' ";
            if(element.checked)
              tagHtml += " CHECKED='CHECKED' ";
  
            if(navigator.appVersion.indexOf("MSIE") != -1 && navigator.appVersion.indexOf("Windows") == -1) // IE5 Mac
              var newElement = document.createElement(tagHtml);
            else
              var newElement = document.createElement("<" + tagHtml + "></"+ element.tagName + ">"); 
            try { newElement.type = element.type; } catch(e) {}; // nail it down for IE5 ?, breaks in IE6
            
          }
         
          // duplicate attributes                    
          for(var i=0; i< element.attributes.length; i++) {
            var attribute = element.attributes[i];
            
            // Get attribute value. 
            if(  attribute.specified || // in IE, the attributes array contains all attributes in the DTD
              attribute.nodeName.toLowerCase() == 'value' ) { // attr.specified buggy in IE?  
              // Add the row suffix if necessary.
              if(  attribute.nodeName.toLowerCase() == "id" || 
                attribute.nodeName.toLowerCase() == "name" ||
                attribute.nodeName.toLowerCase() == "for") {
                              
                if(wFORMS.hasBehavior('hint') && 
                   attribute.nodeValue.indexOf(wFORMS.idSuffix_fieldHint) != -1)  {
                  //leave the field hint suffix at the end of the id.
                  var value = attribute.nodeValue;
                  value= wFORMS.behaviors['repeat'].removeRepeatCountSuffix(value.substr(0,value.indexOf(wFORMS.idSuffix_fieldHint))) + idSuffix + wFORMS.idSuffix_fieldHint;
                }
                else {
                  if(element.tagName.toUpperCase()=="INPUT" && 
                     element.getAttribute('type',false).toLowerCase()=="radio" &&
                     attribute.nodeName.toLowerCase() == "name" && 
                     preserveRadioName) {
                    var value = attribute.nodeValue;            
                  }
                  else {
                    // var value = wFORMS.behaviors['repeat'].removeRepeatCountSuffix(attribute.nodeValue) + idSuffix;
                    var value = attribute.nodeValue + idSuffix;
                  }
                }
              } else {
                // Do not copy the value attribute for text/password/file input
                if(attribute.nodeName.toLowerCase() == "value" &&
                   element.tagName.toUpperCase()=='INPUT'      &&  
                  (element.type.toLowerCase() == 'text'     || 
                   element.type.toLowerCase() == 'password' || 
                   element.type.toLowerCase() == 'hidden' ||
                   element.type.toLowerCase() == 'file')) 
                  var value='';   
                // Do not copy the switch behavior's 'event handled' flag, stored in the rel attribute
                else if(attribute.nodeName.toLowerCase() == "rel" && 
                    attribute.nodeValue.indexOf('wfHandled') != -1) {
                  var value = attribute.nodeValue.replace('wfHandled','');
                } else 
                  var value = attribute.nodeValue;
              }
              // Create attribute and assign value
              switch(attribute.nodeName.toLowerCase()) {
                case "class":
                  newElement.className = value; 
                  break;
                case "style": // inline style attribute (fix for IE)
                  if(element.style && element.style.cssText) 
                    newElement.style.cssText = element.style.cssText; 
                  break;                
                case "onclick": // inline event handler (fix for IE)
                  newElement.onclick     = element.onclick;              
                  break;              
                case "onchange":              
                  newElement.onchange    = element.onchange;              
                  break;              
                case "onsubmit":
                  newElement.onsubmit    = element.onsubmit;              
                  break;              
                case "onmouseover":              
                  newElement.onmouseover = element.onmouseover;              
                  break;              
                case "onmouseout":              
                  newElement.onmouseout  = element.onmouseout;              
                  break;              
                case "onmousedown":
                  newElement.onmousedown = element.onmousedown;              
                  break;              
                case "onmouseup":
                  newElement.onmouseup   = element.onmouseup;              
                  break;              
                case "ondblclick":
                  newElement.ondblclick  = element.ondblclick;              
                  break;              
                case "onkeydown":
                  newElement.onkeydown   = element.onkeydown;              
                  break;              
                case "onkeyup":
                  newElement.onkeyup     = element.onkeyup;              
                  break;              
                case "onblur": 
                  newElement.onblur      = element.onblur;              
                  break;              
                case "onfocus":
                  newElement.onfocus     = element.onfocus;              
                  break;
                default:
                  newElement.setAttribute(attribute.name, value, 0);
              }
            }
          }        
        }
        if(parentElement && newElement) 
          parentElement.appendChild(newElement);
        for(var i=0; i<element.childNodes.length;i++) {
          wFORMS.behaviors['repeat'].replicateTree(element.childNodes[i],newElement,idSuffix, preserveRadioName);
        }
        return newElement;
      }
       } // End wFORMS.behaviors['repeat']
     

   }

// ------------------------------------------------------------------------------------------
// Switch Behavior
// ------------------------------------------------------------------------------------------

 if(wFORMS) {

    // Component properties 
    wFORMS.classNamePrefix_switch     = "switch";
    wFORMS.className_switchIsOn         = "swtchIsOn";    // used to keep track of the switch state on buttons and links (where the checked attribute is not available)
    wFORMS.className_switchIsOff        = "swtchIsOff";
    wFORMS.classNamePrefix_offState    = "offstate";
    wFORMS.classNamePrefix_onState    = "onstate";
    wFORMS.switchScopeRootTag           = "";             // deprecated.  
    
    wFORMS.switchTriggers               = [];        // associative multi-dimensional array (switchname->element Ids)
    wFORMS.switchTargets                = [];        // associative multi-dimensional array (switchname->element Ids)
    
  
    wFORMS.behaviors['switch'] = {

       // ------------------------------------------------------------------------------------------
       // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate
       // ------------------------------------------------------------------------------------------
       evaluate: function(node) {
                
          // Handle Switch Triggers
        // add event handles and populate the wFORMS.switchTriggers 
        // associative array (switchname->element Ids)
        // ------------------------------------------------------------------------------------------        
        if (wFORMS.helpers.hasClassPrefix(node, wFORMS.classNamePrefix_switch)) {

          if(!node.id) node.id = wFORMS.helpers.randomId();
          
          if(!wFORMS.processedForm || !wFORMS.processedForm.id)
            var formId = "undefined";
          else
            var formId = wFORMS.processedForm.id;
          
          // Go through each class (one element can have more than one switch trigger).
          var switchNames = wFORMS.behaviors['switch'].getSwitchNames(node);
          for(var i=0; i < switchNames.length; i++) {
            if(!wFORMS.switchTriggers[formId])
              wFORMS.switchTriggers[formId] = new Array();
            if(!wFORMS.switchTriggers[formId][switchNames[i]]) 
              wFORMS.switchTriggers[formId][switchNames[i]] = new Array();
            if(!wFORMS.switchTriggers[formId][switchNames[i]][node.id]) {
              wFORMS.switchTriggers[formId][switchNames[i]].push(node.id);
            }
          }

          switch(node.tagName.toUpperCase()) {
              
            case "OPTION":
              // get the SELECT element
              var selectNode = node.parentNode;
              while(selectNode && selectNode.tagName.toUpperCase() != 'SELECT') {
                var selectNode = selectNode.parentNode;
              }
              if(!selectNode) { alert('Error: invalid markup in SELECT field ?'); return false;  } // invalid markup
              if(!selectNode.id) selectNode.id = wFORMS.helpers.randomId();

              // Make sure we have only one event handler for the select.
              if(!selectNode.getAttribute('rel') || selectNode.getAttribute('rel').indexOf('wfHandled')==-1) {
                //wFORMS.debug('switch/add event: '+ selectNode.className + ' ' + selectNode.tagName);
                selectNode.setAttribute('rel', (selectNode.getAttribute('rel')||"") + ' wfHandled');
                wFORMS.helpers.addEvent(selectNode, 'change', wFORMS.behaviors['switch'].run);
              }              
              break;

            case "INPUT":              
              if(node.type && node.type.toLowerCase() == 'radio') {
                // Add the onclick event on radio inputs of the same group
                var formElement = node.form;  
                for (var j=0; j<formElement[node.name].length; j++) {
                  var radioNode = formElement[node.name][j];
                  // prevents conflicts with elements with an id = name of radio group
                  if(radioNode.type.toLowerCase() == 'radio') {
                    // Make sure we have only one event handler for this radio input.
                    if(!radioNode.getAttribute('rel') || radioNode.getAttribute('rel').indexOf('wfHandled')==-1) {                
                      wFORMS.helpers.addEvent(radioNode, 'click', wFORMS.behaviors['switch'].run);
                      // flag the node 
                      radioNode.setAttribute('rel', (radioNode.getAttribute('rel')||"") + ' wfHandled');
                    } 
                  }
                }
              } else {
                wFORMS.helpers.addEvent(node, 'click', wFORMS.behaviors['switch'].run);
              }
              break;
            
            default:    
              wFORMS.helpers.addEvent(node, 'click', wFORMS.behaviors['switch'].run);
              break;
          }
        }
        
        // Push targets in the wFORMS.switchTargets array 
        // (associative array with switchname -> element ids)
        // ------------------------------------------------------------------------------------------
        if (wFORMS.helpers.hasClassPrefix(node, wFORMS.classNamePrefix_offState) ||
            wFORMS.helpers.hasClassPrefix(node, wFORMS.classNamePrefix_onState)) {
          
          if(!node.id) node.id = wFORMS.helpers.randomId();

          if(!wFORMS.processedForm || !wFORMS.processedForm.id)
            var formId = "undefined";
          else
            var formId = wFORMS.processedForm.id;
          
          // Go through each class (one element can be the target of more than one switch).
          var switchNames = wFORMS.behaviors['switch'].getSwitchNames(node);
          
          for(var i=0; i < switchNames.length; i++) {
            if(!wFORMS.switchTargets[formId])
              wFORMS.switchTargets[formId] = new Array();
            if(!wFORMS.switchTargets[formId][switchNames[i]]) 
              wFORMS.switchTargets[formId][switchNames[i]] = new Array();
            if(!wFORMS.switchTargets[formId][switchNames[i]][node.id]) 
              wFORMS.switchTargets[formId][switchNames[i]].push(node.id);
            //wFORMS.debug('switch/evaluate: [target] '+ switchNames[i],3);
          }                    
        }
        
        if(node.tagName && node.tagName.toUpperCase()=='FORM') {
          // function to be called when all behaviors have been applied
          wFORMS.onLoadComplete.push({form:node, func: wFORMS.behaviors['switch'].init}); 
          // clear existing triggers/targets for that form.
          wFORMS.behaviors['switch'].clear(node.id);
        }
           },
       
       // ------------------------------------------------------------------------------------------
           // init: executed once evaluate has been applied to all elements
       // ------------------------------------------------------------------------------------------     
       init: function(form) {
      
            if(!form || !form.id)
                var formId = "undefined";
         else
             var formId = form.id; 
         // go through all switch triggers and activate those who are already ON                
         for(var switchName in wFORMS.switchTriggers[formId]) {
          // go through all triggers for the current switch
          for(var i=0; i< wFORMS.switchTriggers[formId][switchName].length; i++) {            
               var element = document.getElementById(wFORMS.switchTriggers[formId][switchName][i]);                           
               if(wFORMS.behaviors['switch'].isTriggerOn(element,switchName)) {
              // if it's a select option, get the select element
              if(element.tagName.toUpperCase()=='OPTION') {
                var element = element.parentNode;
                while(element && element.tagName.toUpperCase() != 'SELECT') {
                  var element = element.parentNode;
                }
              }
              // run the trigger
              wFORMS.behaviors['switch'].run(element);
            }
           }
         }
       },
       
       // ------------------------------------------------------------------------------------------
           // run: executed when the behavior is activated
       // ------------------------------------------------------------------------------------------     
           run: function(e) {
                var element   = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e;
          //wFORMS.debug('switch/run: ' + element.id , 5);  
        
        if(element.form)
          var form = element.form;
        else {
          var form = element.parentNode;
          while(form && form.tagName != "FORM")
            form = form.parentNode;
        }  
        if(!form || !form.id) {
          // switch not within a form tag
          var formId = "undefined";
        } else
          var formId = form.id;
        
        var switches_ON  = new Array();
        var switches_OFF = new Array();
        
        // Get list of triggered switches (some ON, some OFF)
        switch(element.tagName.toUpperCase()) {
          case 'SELECT':
            for(var i=0;i<element.options.length;i++) {
              if(i==element.selectedIndex) {  
                switches_ON  = switches_ON.concat(wFORMS.behaviors['switch'].getSwitchNames(element.options[i]));
              } else {
                switches_OFF = switches_OFF.concat(wFORMS.behaviors['switch'].getSwitchNames(element.options[i]));
              }
            }

            break;
          case 'INPUT':
            if(element.type.toLowerCase() == 'radio') {
              // Go through the radio group.
              
              for(var i=0;i <element.form[element.name].length;i++) { 
                var radioElement = element.form[element.name][i];
                if(radioElement.checked) {
                  switches_ON  = switches_ON.concat(wFORMS.behaviors['switch'].getSwitchNames(radioElement));
                } else {
                  //wFORMS.debug(wFORMS.behaviors['switch'].getSwitchNames(radioElement).length,1);
                  switches_OFF = switches_OFF.concat(wFORMS.behaviors['switch'].getSwitchNames(radioElement));
                }
              }
            } else {
              if(element.checked || wFORMS.helpers.hasClass(element, wFORMS.className_switchIsOn)) {
                switches_ON  = switches_ON.concat(wFORMS.behaviors['switch'].getSwitchNames(element));
              } else {
                switches_OFF = switches_OFF.concat(wFORMS.behaviors['switch'].getSwitchNames(element));
              }              
            }
            break;
          default:
            break;
        }
        
        // Turn off switches first
        for(var i=0; i < switches_OFF.length; i++) {
          // Go through all targets of the switch 
          var elements = wFORMS.behaviors['switch'].getElementsBySwitchName(switches_OFF[i], formId);
          for(var j=0;j<elements.length;j++) {
                                                  
            // only turn off a target if all its triggers are off
            var triggers = wFORMS.switchTriggers[formId][switches_OFF[i]];                        
            var doSwitch = true;
              
            for (var k=0; k < triggers.length; k++) {
              var trigger = document.getElementById(triggers[k]);
              if(wFORMS.behaviors['switch'].isTriggerOn(trigger, switches_OFF[i])) {
                // An element with the REPEAT behavior limits the scope of switches 
                // targets outside of the scope of the switch are not affected. 
                if(wFORMS.behaviors['switch'].isWithinSwitchScope(trigger, elements[j])) {
                  // one of the trigger is still ON. no switch off
                  doSwitch = false;
                }
              }              
            }
            if(doSwitch) {
              wFORMS.behaviors['switch'].switchState(elements[j], wFORMS.classNamePrefix_onState, wFORMS.classNamePrefix_offState);
            }
          }
        }
        // Turn on
        for(var i=0; i < switches_ON.length; i++) {
          var elements = wFORMS.behaviors['switch'].getElementsBySwitchName(switches_ON[i], formId);
          for(var j=0;j<elements.length;j++) {
            // An element with the REPEAT behavior limits the scope of switches 
            // targets outside of the scope of the switch are not affected. 
            if(wFORMS.behaviors['switch'].isWithinSwitchScope(element, elements[j])) {

              wFORMS.behaviors['switch'].switchState(elements[j], wFORMS.classNamePrefix_offState, wFORMS.classNamePrefix_onState);
              //wFORMS.debug('switch/run: [turn on ' + switches_ON[i] + '] ' + elements[j].id , 3);  
            }
          }
        }
           },

       // ------------------------------------------------------------------------------------------
           // clear: executed if the behavior should not be applied anymore
       // ------------------------------------------------------------------------------------------
       clear: function(form) {
               // @TODO: go through wFORMS.switchTriggers to remove events.
               if(form) {
                 wFORMS.switchTriggers[form] = [];    
                 wFORMS.switchTargets[form] = [];
               } else {
                 wFORMS.switchTriggers = [];  
                 wFORMS.switchTargets = [];
               }
           },
       
       
       // ------------------------------------------------------------------------------------------
       // Get the list of switches 
       // Note: potential conflict if an element is both a switch and a target.
       getSwitchNames: function(element) {
        var switchNames = new Array();
        var classNames  = element.className.split(' ');
        for(var i=0; i < classNames.length; i++) {
          // Note: Might be worth keeping a prefix on switchName to prevent collision with reserved names            
          if(classNames[i].indexOf(wFORMS.classNamePrefix_switch) == 0) {
            switchNames.push(classNames[i].substr(wFORMS.classNamePrefix_switch.length+1));
          }
          if(classNames[i].indexOf(wFORMS.classNamePrefix_onState) == 0) {
            switchNames.push(classNames[i].substr(wFORMS.classNamePrefix_onState.length+1));
          }
          else if(classNames[i].indexOf(wFORMS.classNamePrefix_offState) == 0) {
            switchNames.push(classNames[i].substr(wFORMS.classNamePrefix_offState.length+1));
          }
        }
        return switchNames;
      },
      
       // ------------------------------------------------------------------------------------------
      switchState: function(element, oldStateClass, newStateClass) {    
        if(!element || element.nodeType != 1) return;
        if(element.className) {      
          element.className = element.className.replace(oldStateClass, newStateClass);
        }    
        // For  elements that don't have a native state variable (like checked, or selectedIndex)
        if(wFORMS.helpers.hasClass(element, wFORMS.className_switchIsOff)) {
          element.className = element.className.replace(wFORMS.className_switchIsOff, wFORMS.className_switchIsOn);
        } else if(wFORMS.helpers.hasClass(element, wFORMS.className_switchIsOn)) {
          element.className = element.className.replace(wFORMS.className_switchIsOn, wFORMS.className_switchIsOff);
        }
      },
      
      // ------------------------------------------------------------------------------------------
      getElementsBySwitchName: function(switchName, formId) {
        var elements = new Array();
        if(wFORMS.switchTargets[formId][switchName]) {
          for (var i=0; i<wFORMS.switchTargets[formId][switchName].length; i++) {
            var element = document.getElementById(wFORMS.switchTargets[formId][switchName][i]);
            if(element)
              elements.push(element);
          }
        }
        return elements;
      },
      
      // ------------------------------------------------------------------------------------------
      isTriggerOn: function(element, triggerName) {
        if(!element) return false;
        if(element.tagName.toUpperCase()=='OPTION') {
          var selectElement = element.parentNode;
          while(selectElement && selectElement.tagName.toUpperCase() != 'SELECT') {
            var selectElement = selectElement.parentNode;
          }
          if(!selectElement) return false; // invalid markup          
          if(selectElement.selectedIndex==-1) return false; // nothing selected
          // TODO: handle multiple-select
          if(wFORMS.helpers.hasClass(selectElement.options[selectElement.selectedIndex],
                         wFORMS.classNamePrefix_switch + '-' + triggerName)) {
            return true;
          }
        } else {
          if(element.checked || wFORMS.helpers.hasClass(element, wFORMS.className_switchIsOn)) 
            return true;
        }
        return false;
      },
      
      // isWithinSwitchScope: An element with the REPEAT behavior limits the scope of switches 
      // targets outside of the scope of the switch are not affected. 
      // ------------------------------------------------------------------------------------------      
      isWithinSwitchScope: function(trigger, target) {
        
        if(wFORMS.hasBehavior('repeat') && wFORMS.limitSwitchScope == true) { 
          // check if the trigger is in a repeatable/removeable element
          var scope = trigger;
        
          while(scope && scope.tagName && scope.tagName.toUpperCase() != 'FORM' && 
              !wFORMS.helpers.hasClass(scope, wFORMS.className_repeat) &&
                !wFORMS.helpers.hasClass(scope, wFORMS.className_delete) ) {
            scope = scope.parentNode;
          }
          if(wFORMS.helpers.hasClass(scope, wFORMS.className_repeat) || 
             wFORMS.helpers.hasClass(scope, wFORMS.className_delete)) {
            // yes, the trigger is nested in a repeat/remove element
            
            // check if the target is in the same element.
            var scope2 = target;
            while(scope2 && scope2.tagName && scope2.tagName.toUpperCase() != 'FORM' && 
                !wFORMS.helpers.hasClass(scope2, wFORMS.className_repeat) &&
                !wFORMS.helpers.hasClass(scope2, wFORMS.className_delete) ) {
              scope2 = scope2.parentNode;
            }
            if(scope == scope2) {
              return true;  // target & trigger are in the same repeat/remove element    
            } else {
              return false; // target not in the same repeat/remove element,          
            }
          } else {
            return true;    // trigger is not nested in a repeat/remove element, scope unaffected
          }
        } else 
          return true;
      }
       } // END wFORMS.behaviors['switch'] object

       
   }
// ------------------------------------------------------------------------------------------
// Form Validation Behavior
// ------------------------------------------------------------------------------------------
  
   if(wFORMS) {
    // Component properties 
    // wFORMS.functionName_formValidation  is defined at the bottom of this file
    // Those should be moved inside wFORMS.behaviors['validation']. Stays here for now for backward compatibility
         wFORMS.preventSubmissionOnEnter       = true;       // prevents submission when pressing the 'enter' key. Set to true if pagination behavior is used.
       wFORMS.showAlertOnError           = true;       // sets to false to not show the alert when a validation error occurs.
    wFORMS.className_required          = "required";
    wFORMS.className_validationError_msg   = "errMsg";     
    wFORMS.className_validationError_fld  = "errFld";  
    wFORMS.classNamePrefix_validation     = "validate";  
    wFORMS.idSuffix_fieldError        = "-E";

    wFORMS.behaviors['validation'] = {
      
      // Error messages. This may be overwritten in a separate js file for localization or customization purposes.      
      errMsg_required   : "Este campo es obligatorio. ",
      errMsg_alpha     : "Sólo puede introducir letras (a-z, A-Z). Los caractéres numéricos no están permitidos.",
      errMsg_email     : "Esto no es una dirección de email válida.",
      errMsg_integer     : "Introduzca un número entero",
      errMsg_float     : "Introduzca un número (ej. 1.9).",
      errMsg_password   : "Unsafe password. Your password should be between 4 and 12 characters long and use a combinaison of upper-case and lower-case letters.",
      errMsg_alphanum   : "Use sólo caraccteres alfanuméricos [a-z 0-9].",
      errMsg_date     : "Esto no es una fecha válida.",
      errMsg_notification : "%% error(es) detectectados. El formulario no se ha enviado todavía.\nPor favor, verifique que ha rellenado correctamente todos los campos obligatorios.",  // %% will be replaced by the actual number of errors.
      errMsg_custom    : "Please enter a valid value.",
      
      // Class Names
      className_allRequired : "allrequired",
      
      // first page w/ error in a multi-page form
      jumpToErrorOnPage : null,
      currentPageIndex  : -1,
      
      // do not submit fields turned off by switch behavior
      submitSwitchedOffFields : false,
      switchedOffFields : [],
      
       // ------------------------------------------------------------------------------------------
       // evaluate: check if the behavior applies to the given node. Adds event handlers if appropriate
       // ------------------------------------------------------------------------------------------
      evaluate: function(node) {
                 if(node.tagName=="FORM") {
             // functionName_formValidation can be a reference to a function, or a string with the name of the function.
             // avoid using typeof
             if(wFORMS.functionName_formValidation.toString()==wFORMS.functionName_formValidation) {
               // this is a string, not a function
            wFORMS.functionName_formValidation = eval(wFORMS.functionName_formValidation);
             }
                     wFORMS.helpers.addEvent(node,'submit',wFORMS.functionName_formValidation);
                 }
                 // Add onkeydown handler on text inputs to prevent form submission when the enter key is pressed
        if(wFORMS.preventSubmissionOnEnter) { 
          if(node.tagName=='INPUT') {          
            if(!node.type || node.type.toLowerCase()=='text' ||
                             node.type.toLowerCase()=='password' ||
                             node.type.toLowerCase()=='file') {
              wFORMS.helpers.addEvent(node,'keydown', function(e){
                var evt = (e) ? e : window.event;
                if(evt.keyCode==13) {
                  return wFORMS.helpers.preventEvent(evt);
                }
              });
            }
          }
        }
               
           },
       // ------------------------------------------------------------------------------------------
           // init: executed once evaluate has been applied to all elements
       // ------------------------------------------------------------------------------------------     
       init: function() {
       },
       
       // ------------------------------------------------------------------------------------------
           // run: executed when the behavior is activated
       // ------------------------------------------------------------------------------------------            
           run: function(e) {
        var element  = wFORMS.helpers.getSourceElement(e);
        if(!element) element = e;
        //wFORMS.debug('validation/run: ' + element.id , 5);  
        
        var currentPageOnly = arguments.length>1 ? arguments[1]:false;
        // arguments[1] : (wFORMS.hasBehavior('paging') && wFORMS.behaviors['paging'].behaviorInUse);

        wFORMS.behaviors['validation'].switchedOffFields = [];
        wFORMS.behaviors['validation'].jumpToErrorOnPage = null;
        
        // make sure we have the form element
        while (element && element.tagName != 'FORM') {
          element = element.parentNode;
        }    
        
        var nbErrors = wFORMS.behaviors['validation'].validateElement(element, currentPageOnly, true);
        
        // save the value in a property if someone else needs it.
        wFORMS.behaviors['validation'].errorCount = nbErrors;
        
        if (nbErrors > 0) {          
          if(wFORMS.behaviors['validation'].jumpToErrorOnPage) {          
            wFORMS.behaviors['paging'].gotoPage(wFORMS.behaviors['validation'].jumpToErrorOnPage);
          }
          if(wFORMS.showAlertOnError){ wFORMS.behaviors['validation'].showAlert(nbErrors); }
          return wFORMS.helpers.preventEvent(e); 
        }

        // Remove switched-off content if any
        // Note: in multi-page behavior the validation is run on "page next" without submitting the form.
        //       In this situation (currentPageOnly==true) switched-off conditionals should not be removed. 
        if(!wFORMS.behaviors['validation'].submitSwitchedOffFields && !currentPageOnly) {
          for(var i=0; i < wFORMS.behaviors['validation'].switchedOffFields.length; i++) {
            var element = wFORMS.behaviors['validation'].switchedOffFields[i];
            while(element.childNodes[0]) 
              element.removeChild(element.childNodes[0]);
          }
        }        
        return true;
      },
       
      // ------------------------------------------------------------------------------------------
      // remove: executed if the behavior should not be applied anymore
      // ------------------------------------------------------------------------------------------
      remove: function() {
      },
       
       
      // ------------------------------------------------------------------------------------------
      // validation functions
      // ------------------------------------------------------------------------------------------
      validateElement: function(element /*, currentPageOnly, deep */) {

        if(!element) return;

        var deep = arguments.length>2 ? arguments[2] : true;
        
        // used in multi-page forms
        var currentPageOnly = arguments[1] ? arguments[1] : false;        
        
        var wBehavior = wFORMS.behaviors['validation'];    // shortcut
        
        // do not validate elements that are in a OFF-Switch
        // Note: what happens if an element is the target of 2+ switches, some ON and some OFF ?
        if(wFORMS.hasBehavior('switch') && wFORMS.helpers.hasClassPrefix(element,wFORMS.classNamePrefix_offState)) {
          if(!wBehavior.submitSwitchedOffFields) {
            wBehavior.switchedOffFields.push(element);
          }
          return 0;
        }
        // do not validate elements that are not in the current page (Paging Behavior)
        if(wFORMS.hasBehavior('paging') && wFORMS.helpers.hasClass(element,wFORMS.className_paging)) {
          if(!wFORMS.helpers.hasClass(element,wFORMS.className_pagingCurrent) && currentPageOnly)
            return 0;
          wBehavior.currentPageIndex = wFORMS.behaviors['paging'].getPageIndex(element);
        }
        
        var nbErrors = 0;
        
        // check if required
        if(!wBehavior.checkRequired(element)) {
          wBehavior.showError(element, wBehavior.errMsg_required);
          nbErrors++;
          //wFORMS.debug('validation/error: [required]' + element.id + '('+nbErrors+')' , 5);
        } else {
        
          // input format validation
          if (wFORMS.helpers.hasClassPrefix(element,wFORMS.classNamePrefix_validation)) {
    
            var arrClasses = element.className.split(" ");
            for (j=0;j<arrClasses.length;j++) {
              switch(arrClasses[j]) {
                case "validate-alpha":
                  if(!wBehavior.isAlpha(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_alpha);
                    nbErrors++;
                  }
                  break;
                case "validate-alphanum":
                  if(!wBehavior.isAlphaNum(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_alphanum);
                    nbErrors++;
                  }
                  break;
                case "validate-date":
                  if(!wBehavior.isDate(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_date);
                    nbErrors++;
                  }
                  break;
                case "validate-time":
                  /* NOT IMPLEMENTED */
                  break;
                case "validate-email":
                  if(!wBehavior.isEmail(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_email);
                    nbErrors++;
                  }
                  break;
                case "validate-integer":
                  if(!wBehavior.isInteger(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_integer);
                    nbErrors++;
                  }          
                  break;
                case "validate-float":
                  if(!wBehavior.isFloat(element.value)) {
                    wBehavior.showError(element,wBehavior.errMsg_float);
                    nbErrors++;
                  }
                  break;
                case "validate-strongpassword": // NOT IMPLEMENTED
                  if(!wBehavior.isPassword(element.value)) {
                    wBehavior.showError(element, wBehavior.errMsg_password);
                    nbErrors++;
                  }
                  break;
                case "validate-custom": 
                  var pattern = new RegExp("\/([^\/]*)\/([gi]*)");
                  var matches = element.className.match(pattern);
                  if(matches[0]) {                    
                    var validationPattern = new RegExp(matches[1],matches[2]);
                    if(!element.value.match(validationPattern)) {
                      wBehavior.showError(element, wBehavior.errMsg_custom);
                      nbErrors++;                      
                    }
                  }                              
                  break;                  
              } // end switch
            } // end for
          }
        } // end validation check
        
        // remove previous error flags if any.
        if(nbErrors==0) {
          wBehavior.removeErrorMessage(element);
        } else {
          // flag the first page with an error (if multi-page form)
          if(wBehavior.currentPageIndex>0 && !wBehavior.jumpToErrorOnPage) {
            wBehavior.jumpToErrorOnPage = wBehavior.currentPageIndex;
          }
        }
          
        // recursive loop          
        if(deep) {
          for(var i=0; i < element.childNodes.length; i++) {
            if(element.childNodes[i].nodeType==1) { // Element Nodes only
              nbErrors += wBehavior.validateElement(element.childNodes[i], currentPageOnly, deep);
            }
          }
        }
        
        return nbErrors;
      },
      
      // ------------------------------------------------------------------------------------------
      checkRequired: function(element) {
        var wBehavior = wFORMS.behaviors['validation'];    // shortcut        

        if(wFORMS.helpers.hasClass(element,wFORMS.className_required)) {
          switch(element.tagName.toUpperCase()) {
            case "INPUT":
              var inputType = element.getAttribute("type");
              if(!inputType) inputType = 'text'; // handles lame markup
              switch(inputType.toLowerCase()) {
                case "checkbox":
                  return element.checked; 
                  break;
                case "radio":
                  return element.checked; 
                  break;
                default:
                  return !wBehavior.isEmpty(element.value);
              }
              break;
            case "SELECT":              
              if(element.selectedIndex==-1) {
                // multiple select with no selection
                return false;
              } else                         
                return !wBehavior.isEmpty(element.options[element.selectedIndex].value);
              break;
            case "TEXTAREA":
              return !wBehavior.isEmpty(element.value);
              break;
            default:
              return wBehavior.checkOneRequired(element);
              break;
          }   
        } else if(wFORMS.helpers.hasClass(element,wBehavior.className_allRequired)) {
          return wBehavior.checkAllRequired(element);
        }
        return true;
      },
      checkOneRequired: function(element) {  
        if(element.nodeType != 1) return false;
        var tagName = element.tagName.toUpperCase();
        var wBehavior = wFORMS.behaviors['validation'];
        
        if(tagName == "INPUT" || tagName == "SELECT" || tagName == "TEXTAREA" ) {
          var value = wBehavior.getFieldValue(element);  
          if(!wBehavior.isEmpty(value)) {          
            return true;
          }      
        }
        for(var i=0; i<element.childNodes.length;i++) {
          if(wBehavior.checkOneRequired(element.childNodes[i])) return true;
        }
        return false;
      },
      checkAllRequired: function(element)  {
        
        if(element.nodeType != 1) return true;
        var tagName = element.tagName.toUpperCase();
        var wBehavior = wFORMS.behaviors['validation'];

        if(tagName == "INPUT" || tagName == "SELECT" || tagName == "TEXTAREA" ) {
          var value = wBehavior.getFieldValue(element);  
          if(wBehavior.isEmpty(value)) {          
            return false;
          }      
        }
        for(var i=0; i<element.childNodes.length;i++) {
          if(!wBehavior.checkAllRequired(element.childNodes[i])) return false;
        }
        return true;
      },
      getFieldValue: function(element) {
        var value = null;
        if(element && element.tagName) {
          if(element.tagName.toUpperCase() == "INPUT") {
            var inputType = element.getAttribute("type");
            if(!inputType) inputType = 'text'; // handles lame markup
          
            switch(inputType.toLowerCase()) {
              case "checkbox": 
                value = element.checked?element.value:null; 
                break;
              case "radio":                
                var radioGroup = element.form[element.name];               
                for (var i = 0; i< radioGroup.length; i++) {
                    if (radioGroup[i].checked) {
                      if(!value) value = new Array();
                    value[value.length] = radioGroup[i].value;
                    }
                }                 
                break;
              default:
                value = element.value;
            }
          } else if(element.tagName.toUpperCase() == "SELECT") {  
            if(element.selectedIndex!=-1)                                
              value = element.options[element.selectedIndex].value            
            else
              value = null; // multiple select with no selection
          } else if(element.tagName.toUpperCase() == "TEXTAREA") {
            value = element.value;
          }
        }
        return value;
      },
      // ------------------------------------------------------------------------------------------
      isEmpty: function(s) {        
        var regexpWhitespace = /^\s+$/;
        return  ((s == null) || (s.length == 0) || regexpWhitespace.test(s));
      },
      isAlpha: function(s) {
        var regexpAlphabetic = /^[a-zA-Z\s]+$/; // Add ' and - ?
        return wFORMS.behaviors['validation'].isEmpty(s) || regexpAlphabetic.test(s);
      },
      isAlphaNum: function(s) {
        var validChars = /^[\w\s]+$/;
        return wFORMS.behaviors['validation'].isEmpty(s) || validChars.test(s);
      },
      isDate: function(s) {
        var testDate = new Date(s);
        return wFORMS.behaviors['validation'].isEmpty(s) || !isNaN(testDate);
      },
      isEmail: function(s) {
        var regexpEmail = /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/;
        return wFORMS.behaviors['validation'].isEmpty(s) || regexpEmail.test(s);
      },
      isInteger: function(s) {
        var regexp = /^[+]?\d+$/;
        return wFORMS.behaviors['validation'].isEmpty(s) || regexp.test(s);
      },
      isFloat: function(s) {    
        return wFORMS.behaviors['validation'].isEmpty(s) || !isNaN(parseFloat(s));
      },
      // NOT IMPLEMENTED
      isPassword: function(s) {
        // Matches strong password : at least 1 upper case letter, one lower case letter. 4 characters minimum. 12 max.
        //var regexp = /^(?=.*[a-z])(?=.*[A-Z])(?!.*\s).{4,12}$/;  // <= breaks in IE5/Mac
        return wFORMS.behaviors['validation'].isEmpty(s);
      },
      
      // ------------------------------------------------------------------------------------------    
      // Error Alert Functions
      // ------------------------------------------------------------------------------------------    
      showError: function (element,errorMsg) {    
        // remove existing error message if any.
        wFORMS.behaviors['validation'].removeErrorMessage(element);
        
        if (!element.id) element.id = wFORMS.helpers.randomId(); // we'll need an id here.    
        // Add error flag to the field
        element.className += " " + wFORMS.className_validationError_fld;
        // Prepare error message
        var msgNode = document.createTextNode(" " + errorMsg);
        // Find error message placeholder.
        var fe = document.getElementById(element.id +  wFORMS.idSuffix_fieldError);
        if(!fe) { // create placeholder.
          fe = document.createElement("div"); 
          fe.setAttribute('id', element.id +  wFORMS.idSuffix_fieldError);      
          // attach the error message after the field label if possible
          var fl = document.getElementById(element.id +  wFORMS.idSuffix_fieldLabel);
          if(fl)
            fl.parentNode.insertBefore(fe,fl.nextSibling);
          else
            // otherwise, attach it after the field tag.
            element.parentNode.insertBefore(fe,element.nextSibling);
        }
        // Finish the error message.
        fe.appendChild(msgNode);    
        fe.className += " " + wFORMS.className_validationError_msg;
      },
      
      showAlert: function (nbTotalErrors) {
         alert(wFORMS.behaviors['validation'].errMsg_notification.replace('%%',nbTotalErrors));
      },
      
      removeErrorMessage: function(element) {
        if(wFORMS.helpers.hasClass(element,wFORMS.className_validationError_fld)) {
          var rErrClass     = new RegExp(wFORMS.className_validationError_fld,"gi");
          element.className = element.className.replace(rErrClass,"");
          var errorMessage  = document.getElementById(element.id + wFORMS.idSuffix_fieldError);
          if(errorMessage)  {        
            errorMessage.innerHTML=""; 
          }
        }
      }
          
       } // End wFORMS.behaviors['validation']
     
    wFORMS.functionName_formValidation = wFORMS.behaviors['validation'].run;


    // ----------------------------------------------------------------------
    // wForms 1.0 backward compatibility
    // ----------------------------------------------------------------------
    wFORMS.formValidation = wFORMS.behaviors['validation'].run;
    
    // Error messages. 
    wFORMS.arrErrorMsg = new Array(); 
    wFORMS.arrErrorMsg[0] = wFORMS.behaviors['validation'].errMsg_required;  
    wFORMS.arrErrorMsg[1] = wFORMS.behaviors['validation'].errMsg_alpha;       
    wFORMS.arrErrorMsg[2] = wFORMS.behaviors['validation'].errMsg_email;    
    wFORMS.arrErrorMsg[3] = wFORMS.behaviors['validation'].errMsg_integer;    
    wFORMS.arrErrorMsg[4] = wFORMS.behaviors['validation'].errMsg_float;
    wFORMS.arrErrorMsg[5] = wFORMS.behaviors['validation'].errMsg_password;
    wFORMS.arrErrorMsg[6] = wFORMS.behaviors['validation'].errMsg_alphanum;
    wFORMS.arrErrorMsg[7] = wFORMS.behaviors['validation'].errMsg_date;
    wFORMS.arrErrorMsg[8] = wFORMS.behaviors['validation'].errMsg_notification;
    
   }
   
   
   
