/***

    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         : "This field is required. ",
                        errMsg_alpha                 : "The text must use alphabetic characters only (a-z, A-Z). Numbers are not allowed.",
                        errMsg_email                 : "This does not appear to be a valid email address.",
                        errMsg_integer                 : "Please enter an integer.",
                        errMsg_float                 : "Please enter a number (ex. 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         : "Please use alpha-numeric characters only [a-z 0-9].",
                        errMsg_date                 : "This does not appear to be a valid date.",
                        errMsg_notification : "%% error(s) detected. Your form has not been submitted yet.\nPlease check the information you provided.",  // %% 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;
                
   }
   
   
   
