/***

wForms 2.0
a javascript extension to web forms. 

Build $Mon, 11 Jun 2007 14:33:25 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 "checked":
                                    // skip checked attribute
                                    newElement.checked = false;
                                    break;
                                case "selected":
                                    // skip selected attribute
                                    newElement.selected = false;
                                    break;
                                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;

                    var preventEvent = false;

                    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:
                            if (!wFORMS.behaviors['switch'].isTriggerOn(element))
                                switches_ON = switches_ON.concat(wFORMS.behaviors['switch'].getSwitchNames(element));
                            else
                                switches_OFF = switches_OFF.concat(wFORMS.behaviors['switch'].getSwitchNames(element));

                            // 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);
                            }
                            preventEvent = true;
                            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);	
                            }
                        }
                    }
                    if (preventEvent)
                        return wFORMS.helpers.preventEvent(e);
                },

                // ------------------------------------------------------------------------------------------
                // 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);
                    }
                },

                // ------------------------------------------------------------------------------------------
                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;

}
