text: /**
   * The inputEx Library
   * @module inputEx
   */
  /*global inputEx: false, YAHOO: false */
  (function() {
   
   var lang = YAHOO.lang;
   
  /**
   * The inputEx method lets you create a field from the JSON definition:
   * <pre>
   *    inputEx({type: 'string', name: 'company', label: 'Your company' })
   * </pre>
   * Build a field from an object like: { type: 'color' or fieldClass: inputEx.ColorField, ... }<br />
   * If the neither type or fieldClass are found, it uses inputEx.StringField
   *
   * @class inputEx
   * @static
   * @param {Object} fieldOptions
   * @param {inputEx.Group|inputEx.Form|inputEx.ListField|inputEx.CombineField} (optional) parentField The parent field instance
   * @return {inputEx.Field} Created field instance
   */
  inputEx = function(fieldOptions, parentField) {
     var fieldClass = null,
         inputInstance;
     
  	if(fieldOptions.type) {
  	   fieldClass = inputEx.getFieldClass(fieldOptions.type);
  	   if(fieldClass === null) fieldClass = inputEx.StringField;
  	}
  	else {
  	   fieldClass = fieldOptions.fieldClass ? fieldOptions.fieldClass : inputEx.StringField;
  	}
  
     // Instanciate the field
     
     // Retro-compatibility with deprecated inputParams Object
     if (lang.isObject(fieldOptions.inputParams)) {
        inputInstance = new fieldClass(fieldOptions.inputParams);
        
     // New prefered way to instanciate a field
     } else {
        inputInstance = new fieldClass(fieldOptions);
     }
  
  	// If the parentField argument is provided
  	if(parentField) {
  		inputInstance.setParentField(parentField);
  	}
  
     // Add the flatten attribute if present in the params
     /*if(fieldOptions.flatten) {
        inputInstance._flatten = true;
     }*/
  	  
     return inputInstance;
  };
  
  lang.augmentObject(inputEx, {
     
     VERSION: "0.7.1",
     
     /**
      * Url to the spacer image. This url schould be changed according to your project directories
      * @type String
      */
     spacerUrl: "images/space.gif", // 1x1 px
     
     /**
      * Field empty state constant
      * @type String
      */
     stateEmpty: 'empty',
     
     /**
      * Field required state constant
      * @type String
      */
     stateRequired: 'required',
     
     /**
      * Field valid state constant
      * @type String
      */
     stateValid: 'valid',
     
     /**
      * Field invalid state constant
      * @type String
      */
     stateInvalid: 'invalid',
     
     /**
      * Associative array containing field messages
      */
  	messages: {
  		required: "This field is required",
  		invalid: "This field is invalid",
  		valid: "This field is valid",
  		defaultDateFormat: "m/d/Y",
  		months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  		timeUnits: { SECOND: "seconds", MINUTE: "minutes", HOUR: "hours", DAY: "days", MONTH: "months", YEAR: "years" }
  	},
     
     /**
      * inputEx widget namespace
      * @static 
      */
     widget: {},
     
     /**
      * inputEx mixin namespace
      * @static 
      */
     mixin: {},
     
     /**
      * Associative array containing common regular expressions
      */
     regexps: {
        email: /^[a-z0-9!\#\$%&'\*\-\/=\?\+\-\^_`\{\|\}~]+(?:\.[a-z0-9!\#\$%&'\*\-\/=\?\+\-\^_`\{\|\}~]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,6}$/i,
        url: /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(\:[0-9]{1,5})?(([0-9]{1,5})?\/.*)?$/i,
        password: /^[0-9a-zA-Z\x20-\x7E]*$/
     },
     
     /**
      * Hash between inputEx types and classes (ex: <code>inputEx.typeClasses.color = inputEx.ColorField</code>)<br />
      * Please register the types with the <code>registerType</code> method
      */
     typeClasses: {},
     
     /**
      * Property to globally turn on/off the browser autocompletion
      * (used as default autocomplete option value by StringField, Form and their subclasses)
      */
     browserAutocomplete: true,
     
     /**
      * When you create a new inputEx Field Class, you can register it to give it a simple type.
      * ex:   inputEx.registerType("color", inputEx.ColorField);
      * @static
      * @param {String} type String used as the inputEx field type
      * @param {Class} fieldClass Field Class to register as this type
  	 * @param {Array} groupOptions List of inputEx field description for each option
  	 * @param {Boolean} dontInherit Won't inherhit the parent field properties if set to true
      */
     registerType: function(type, fieldClass, groupOptions, dontInherit) {
        if(!lang.isString(type)) {
           throw new Error("inputEx.registerType: first argument must be a string");
        }
        if(!lang.isFunction(fieldClass)) {
           throw new Error("inputEx.registerType: second argument must be a function");
        }
        this.typeClasses[type] = fieldClass;
        
        // Setup the groupOptions property on the class
        var opts = [];
        if(lang.isArray(groupOptions)) { opts = groupOptions; }
        if(fieldClass.superclass && !dontInherit && lang.isArray(fieldClass.superclass.constructor.groupOptions) ) {
           opts = fieldClass.superclass.constructor.groupOptions.concat(opts);
        }
        fieldClass.groupOptions = opts;
     },
     
     /**
      * Returns the class for the given type
      * ex: inputEx.getFieldClass("color") returns inputEx.ColorField
      * @static
      * @param {String} type String type of the field
      */
     getFieldClass: function(type) {
        return lang.isFunction(this.typeClasses[type]) ? this.typeClasses[type] : null;
     },
     
     /**
      * Get the inputex type for the given class (ex: <code>inputEx.getType(inputEx.ColorField)</code> returns "color")
      * @static
      * @param {inputEx.Field} FieldClass An inputEx.Field or derivated class
      * @return {String} returns the inputEx type string or <code>null</code>
      */
     getType: function(FieldClass) {
        for(var type in this.typeClasses) {
           if(this.typeClasses.hasOwnProperty(type) ) {
              if(this.typeClasses[type] == FieldClass) {
                 return type;
              }
           }
        }
        return null;
     },
     
     /**
      * @deprecated Kept for backward compatibility (alias for inputEx() )
      * @param {Object} fieldOptions
      * @return {inputEx.Field} Created field instance
      */
     buildField: function(fieldOptions) {      
        return inputEx(fieldOptions);
     },
     
     /**
      * Helper function to set DOM node attributes and style attributes.
      * @static
      * @param {HTMLElement} el The element to set attributes to
      * @param {Object} domAttributes An object containing key/value pairs to set as node attributes (ex: {id: 'myElement', className: 'myCssClass', ...})
      * @param {Object} styleAttributes Same thing for style attributes. Please use camelCase for style attributes (ex: backgroundColor for 'background-color')
      */
     sn: function(el,domAttributes,styleAttributes){
        if(!el) { return; }
  		var i;
        if(domAttributes){
           for(i in domAttributes){
              var domAttribute = domAttributes[i];
              if( lang.isFunction(domAttribute) ){
                 continue;
              }
              if(i=="className"){
                 i="class";
                 el.className=domAttribute;
              }
              if(domAttribute!==el.getAttribute(i)){
                 try{
                    if(domAttribute===false){
                       el.removeAttribute(i);
                    }else{
                       el.setAttribute(i,domAttribute);
                    }
                 }
                 catch(err){
                    //console.log("WARNING: WireIt.sn failed for "+el.tagName+", attr "+i+", val "+domAttribute);
                 }
              }
           }
        }
  
        if(styleAttributes){
           for(i in styleAttributes){
              if( lang.isFunction(styleAttributes[i]) ){
                 continue;
              }
              if(el.style[i]!=styleAttributes[i]){
                 el.style[i]=styleAttributes[i];
              }
           }
        }
     },
  
  
     /**
      * Helper function to create a DOM node. (wrapps the document.createElement tag and the inputEx.sn functions)
      * @static
      * @param {String} tag The tagName to create (ex: 'div', 'a', ...)
      * @param {Object} [domAttributes] see inputEx.sn
      * @param {Object} [styleAttributes] see inputEx.sn
      * @param {String} [innerHTML] The html string to append into the created element
      * @return {HTMLElement} The created node
      */
     cn: function(tag, domAttributes, styleAttributes, innerHTML) {
          if (tag == 'input' && YAHOO.env.ua.ie && YAHOO.env.ua.ie < 9) { //only limit to input tag that has no tag body
              var strDom = '<' + tag;
              if (domAttributes!=='undefined'){
                  for (var k in domAttributes){
                      strDom += ' ' + (k === "className" ? "class" : k) + '="' + domAttributes[k] + '"';
                  }
              }
              strDom += '/' + '>';
              return document.createElement(strDom);
  
          } else {
              var el = document.createElement(tag);
              this.sn(el, domAttributes, styleAttributes);
              if (innerHTML) {
                  el.innerHTML = innerHTML;
              }
              return el;
          }
      },
     
     
     /**
      * Find the position of the given element. (This method is not available in IE 6)
      * @static
      * @param {Object} el Value to search
      * @param {Array} arr The array to search
      * @param {Function} (optional) fn A function to define another way to test inclusion of el than === (returns a boolean)
      * @return {number} Element position, -1 if not found
      */
  	indexOf: function(el,arr,fn) {
  	
  		var l=arr.length,i;
  		
  		if ( !lang.isFunction(fn) ) { fn = function(elt,arrElt) { return elt === arrElt; }; }
  		
  		for ( i = 0 ;i < l ; i++ ) {
  			if ( fn.call({}, el, arr[i]) ) { return i; }
  		}
  		
  		return -1;
  	},
  
     
     /**
      * Create a new array without the null or undefined values
      * @static
      * @param {Array} arr The array to compact
      * @return {Array} The new array
      */
     compactArray: function(arr) {
        var n = [], l=arr.length,i;
        for(i = 0 ; i < l ; i++) {
           if( !lang.isNull(arr[i]) && !lang.isUndefined(arr[i]) ) {
              n.push(arr[i]);
           }
        }
        return n;
     },
  
  	/**
  	 * Return a string without accent (only on lowercase)
  	 * @static
  	 * @param {String} str The string
  	 * @return {String} String without accent
  	 */
  	removeAccents: function (str) {
  	   return str.replace(/[àáâãäå]/g,"a").
  					  replace(/[èéêë]/g,"e").
  					  replace(/[ìíîï]/g,"i").
  					  replace(/[òóôõö]/g,"o").
  					  replace(/[ùúûü]/g,"u").
  					  replace(/[ýÿ]/g,"y").
  					  replace(/[ñ]/g,"n").
  					  replace(/[ç]/g,"c").
  					  replace(/[œ]/g,"oe").
  					  replace(/[æ]/g,"ae");
  	},
  	
  	/**
  	 * String replaced by some html entities
  	 * @static
  	 * @param {String} str The string
  	 * @return {String} String replaced by some html entities
  	 */
  	htmlEntities: function (str) {
  	   return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  	}
     
  });
  
  })();
  
  
  // The main inputEx namespace shortcut
  YAHOO.inputEx = inputEx;
  