/**
 * Javascript framework for design patterns 
 * @fileoverview IAJS global namespace object
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 * 
 */
if (typeof IAJS == "undefined") {
	var IAJS = {};
}
IAJS.UNDEF = "undefined";
IAJS.RESOURCE = {};
IAJS.RESOURCE.log = {DEFAULT: 0, INIT: 1, VALIDATION: 2, BOOTSTRAP: 3, MASTER: 4, SUBORDINATE: 5, EVENT: 6}; //valid source to log to
//
IAJS.event = {
	logEvent : new YAHOO.util.CustomEvent("logEvent", this)
};
	
/**
 * Initialize
 */
IAJS.init = function(){}
/**
 * Provides controllers used by the library
 * @class IAJS.CONTROLLER
 * @member IAJS.CONTROLLER
 */
IAJS.CONTROLLER = function(){}
/**
 * Collection of valid controllers
 * @class controllerCollection
 * @base IAJS
 * @see #controllers manager for collection 
 */
IAJS.controllerCollection = IAJS.controllerCollection || {};
/**
 * Collection of valid forms
 * @class formCollection
 * @base IAJS
 * @see #forms manager for collection
 */
IAJS.formCollection = IAJS.formCollection || {};
/**
 * Provides validation used by the library
 * @member IAJS.VALIDATION
 */
IAJS.VALIDATION = function(){}
/**
 * @class IAJS.OBSERVER
 */
IAJS.OBSERVER = function(){
	showEvent: null;
}
/**
 * @base IAJS.OBSERVER
 */
IAJS.OBSERVER.getInstance = function(){
	if(!this.showEvent){
		this.showEvent = new YAHOO.util.CustomEvent("showEvent", this);
	}
 	return this.showEvent;
}
/**
 * @class
 */
IAJS.form = function(){};

/**
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 * 
 */

 
/**
 * Formats a date according to a formatting string.
 * @param {string} format formatting string, accepts special characters, which must be enclosed by "%" (to use "%" literally, use "%%"), the following characters are recognized:	
 * d - day of the month 2 digits (01-31)
 * j - day of the month (1-31)
 * N - 1=Monday, 2=Tuesday, etc (1-7)
 * w - 0=Sunday, 1=Monday (0-6)
 * z - day of the year (1-365)
 * W - week of the year (1-52)
 * m - 2 digit month number (01-12)
 * n - month number (1-12)
 * t - Days in the month (28-31)
 * L - leap year (0 no, 1 yes)
 * Y - four digit year (Ex. 1979, 2006)
 * y - two digit year (Ex. 79, 06)
 * a - am or pm
 * A - AM or PM
 * g - 12 hour (1-12)
 * G - 24 hour c (0-23)
 * h - 2 digit 12 hour (01-12)
 * H - 2 digit 24 hour (00-23)
 * i - 2 digit minutes (00-59)
 * s - 2 digit seconds (00-59)
 * S - seconds (0-59)
 * ms - 3 digits milliseconds(000-999)
 * O - offset Timezone (hours)
 * @param {string} userFunctions object where the properties must be names of user functions,
 * each property value must be a function which receives two arguments, the first
 * will be the own Date object and the second if a function that receives
 * as argument one of the special characters defined above and returns its value.
 */
Date.prototype.format = function(m, r){
    var d = this, a, fix = function(n, c){return (n = n + "").length < c ? new Array(++c - n.length).join("0") + n : n};	
    var r = r || {}, f = {j: function(){return d.getDate()}, w: function(){return d.getDay()},
        y: function(){return (d.getFullYear() + "").slice(2)}, Y: function(){return d.getFullYear()},
        n: function(){return d.getMonth() + 1}, m: function(){return fix(f.n(), 2)},
        g: function(){return d.getHours() % 12 || 12}, G: function(){return d.getHours()},
        H: function(){return fix(d.getHours(), 2)}, h: function(){return fix(f.g(), 2)},
        d: function(){return fix(f.j(), 2)}, N: function(){return f.w() + 1},
        i: function(){return fix(d.getMinutes(), 2)}, s: function(){return fix(d.getSeconds(), 2)}, S: function(){return d.getSeconds()},
        ms: function(){return fix(d.getMilliseconds(), 3)}, a: function(){return d.getHours() > 11 ? "pm" : "am"},
        A: function(){return f.a().toUpperCase()}, O: function(){return d.getTimezoneOffset() / 60},
        z: function(){return (d - new Date(d.getFullYear() + "/1/1")) / 864e5 >> 0},
        L: function(){var y = f.Y(); return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0},
        t: function(){var n; return (n = d.getMonth() + 1) == 2 ? 28 + f.L() : n & 1 && n < 8 || !(n & 1) && n > 7 ? 31 : 30},
        W: function(){
            var a = f.z(), b = 364 + f.L() - a, nd = (new Date(d.getFullYear() + "/1/1").getDay() || 7) - 1;
            return (b <= 2 && ((d.getDay() || 7) - 1) <= 2 - b) ? 1 :
                (a <= 2 && nd >= 4 && a >= (6 - nd)) ? new Date(d.getFullYear() - 1 + "/12/31").format("%W%") :
                (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);
        }
    }
    return m.replace(/%(.*?)%/g, function(t, s){
        return r[s] ? r[s](d, function(s){return f[s] && f[s]();}) : f[s] ? f[s]() : "%" + (s && s + "%");
    });
}
/**
 * Replace all occurences of a string in a string
 * @param {string} needle the string to replace
 * @param {string} replacement the replacement
 */
String.prototype.replaceAll = function(needle,replacement)
{
  var str = this
  while(str.indexOf(needle)>-1)
  {
	str = str.replace(needle,replacement);
  }
  return str;
}
/**
 * Pad a string to a certain length with another string
 * @param {int} length amount of characters that the string must have
 * @param {string} substring that will be concatenated
 * @param {string} type specifies the side where the concatenation will happen, where: 0 = left, 1 = right and 2 = both side
 * @returns the string with a substring padded on the left, right or both sides.
 */
String.prototype.pad = function(l, s, t){
	return s || (s = " "), (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length) + 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2)) + this + s.substr(0, l - t) : this;
};
/**
 * Capitalizes the first letter of a string and downcases all the others.
 */
String.prototype.capitalize = function(){
  return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
/**
 * Camelize string
 */
String.prototype.camelize = function() {
  var parts = this.split('-'), len = parts.length;
  if (len == 1) return parts[0];

  var camelized = this.charAt(0) == '-'
	? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
	: parts[0];

  for (var i = 1; i < len; i++)
	camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

  return camelized;
}
/**
 * 
 * @param {string} date the date in forgiving format
 */
String.prototype.toReadableDate = function(format)
{
  var date_arr = this.split("-");
  var day = date_arr[0];
  var month = date_arr[1];
  var year = date_arr[2];
  var d = new Date(year,month-1,day); // why -1 ?
  var functions = {
    DayName: function(d, f){
        return LOCALIZE.days[f('w')];
    },
    MonthName: function(d, f){
        return LOCALIZE.month[f('n') - 1];
    }
  }
  return d.format(format, functions);

}
/**
 * 
 * @param {string} date the date in forgiving format
 */
String.prototype.toReadableTime = function(format)
{
  var time_arr = this.split(/[\s\.,\/\+_,:=]+/);
  var hour = time_arr[0];
  var minute = time_arr[1];
  var second = time_arr[2];
  var d = new Date(1970,1,1,hour,minute,second); 
  if (format)
	return d.format(format);
  else
    return d;
}
/**
* Converts a phonenumber from a forgiving format to more structured format
* by removing all legal none digit characters
* @param {string} phone the phonenumber to format
* @returns {string} formated phone
*/
String.prototype.toReadablePhone = function(){
	phoneString = this.replace(/([\\\/\.\-\(\)\s,])/ig, ""); //remove legal none digit characters: "blank", . : - ( ) / \
	return phoneString.replace(/^00/g, "+"); //replace leading 00 with +
}
/**
 * Converts a date from the forgiving format to the structured format (31-12-1900), the date must be in day month year order
 * year: 100 will be 2100, 0100 will be 100
 */
String.prototype.toStructuredDate = function()
{
	/*
	 * year :
	 * 	600 will 
	 */
	date_arr = this.toStructuredDateArray();
	var day = date_arr[0];
	var month = date_arr[1];
	var year = date_arr[2] || new Date().getUTCFullYear();
	if (year && year.length < 4) year = "2".pad(4-year.length,"0",1) + year;
	return day.pad(2,"0") + "-" + (month && month.pad(2,"0")) + "-" + year;
}
/**
 * Converts a date from the forgiving format to an array(day, month, year) in structured format, the date must be in day month year order
 */
String.prototype.toStructuredDateArray = function(){
	val = this.replace(/^[\s]+/, "");// remove leading spaces
	return val.split(/[\s\.,\/\+_,:=\-]+/); // split string : whitespace . / \ + _ , : =
}

/**
 * Converts a time from the forgiving format to the structured format hh:mm:ss
 * @param {string} date the date in forgiving format
 * @param {Boolean} asArray return values as array instead of String (optional, default false)
 * @return {string} date in hh:mm:ss format
 */
String.prototype.toStructuredTime = function(asArray){
//  var bad_separators = [" ",".","/","+","_",",","-","="];
  
  timeString = this.toLowerCase();
  timeString = timeString.replace(/^[\s]+/, "");// remove leading spaces
  timeString = timeString.replace(/[\s\.,\/\+_,=:\-]+/g, ":");// replace:  whitespace . / \ + _ , : = - with :
  //for(i=0;i<bad_separators.length;i++) timeString = timeString.replaceAll(bad_separators[i],":");
  if ((/[^0-9|u|h|m|s|:]+/).test(timeString)) return false; //there should only be legal characters left
  //check if hour, minute, seconds is used or just seperators
  if(timeString.match(/[u|h|m|s]/)){
  	  // null if not match
	  var hour = timeString.match(/(\d+)[h|u]/);
	  var minute = timeString.match(/(\d+)m/);
	  var second = timeString.match(/(\d+)s/);
	  // equal null to 0
	  hour = (!hour)? "0" : hour[1];
	  minute = (!minute)? "0" : minute[1];
	  second = (!second)? "0" : second[1];  	
  } else {
	  var time_arr = timeString.split(":");
	  var hour = time_arr[0] || "0";
	  var minute = time_arr[1] || "0";
	  var second = time_arr[2] || "0";  	
  }
  return (asArray)? new Array(hour,minute,second) : hour.pad(2,"0") + ":" + minute.pad(2,"0") + ":" + second.pad(2,"0");
  //if (asArray) return new Array(hour,minute,second);
  //return hour.pad(2,"0") + ":" + minute.pad(2,"0") + ":" + second.pad(2,"0");
}
/**
 * format as url
 * @param {String} assumeSheme  The sheme assumed is no scheme is provid (optional)  
 */
String.prototype.toStructuredUrl = function(assumeScheme){
	if (this.length == 0) return;
	urlString = this.toLowerCase();
	urlString = urlString.replace(/\s+$/);  //remove all trailing spaces
	if (assumeScheme && !(/:\/\//).test(urlString)) urlString = assumeScheme + "://" + urlString; // if no '://' is provided in url prefix with assumeSheme 
	return urlString;
}
/**
 * removes seperator characters from string (removes .(dot),-(hyp),/(slash),\(backslash),white-space)
 * @param {string} date the date in forgiving format
 */
String.prototype.removeSeperators = function() {
   return this.replace(/([\.\-\/\\\s,])/ig, "");
}

/**
 * Returns the position of the first occurrence of the argument within the array. If the argument doesn't exist in the array, returns -1.
 * IE6 does not have this. So we include it here.
 * 
 */
Array.prototype.indexOf = function(object){                                                                                                
  for (var i = 0, length = this.length; i < length; i++)                                                                   
	if (this[i] == object) return i;                                                                                       
  return -1;                                                                                                               
};/**
 * Manage controllers  
 * @class IAJS.controllerManager
 * @copyight 2007-2008
 * @version 1.0.5 
 */
IAJS.controllerManager = {
	
	event : { 
		/**
		* @event {object} controllerAdd controller was added to the controller collection
 		* <code>&lt;String&gt; type</code> controllerAdd<br />
 		* <code>&lt;String&gt; id</code> id of the controller that was added<br />
		* <p><strong>Usage:</strong><br>
		* 	<code>
		* 		var handler = function(type, args){var controllerId = args[0].id};<br>
		* 		IAJS.controllerManager.event.controllerAdd(handler);
		* 	</code>
		* </p>
		*/
		controllerAdd : new YAHOO.util.CustomEvent("controllerAdd", IAJS.controllerManager),
		/**
		* @event {object} controllerRemove controller was added to the controller collection
 		* <code>&lt;String&gt; type</code> controllerRemove<br />
 		* <code>&lt;String&gt; id</code> id of the controller that was removed<br />
		* <p><strong>Usage:</strong><br>
		* 	<code>
		* 		var handler = function(type, args){var controllerId = args[0].id};<br>
		* 		IAJS.controllerManager.event.controllerAdd(handler);
		* 	</code>
		* </p> 
		*/
		controllerRemove : new YAHOO.util.CustomEvent("controllerRemove", IAJS.controllerManager),
		/**
		 * 
		 */
		 controllerError : new YAHOO.util.CustomEvent("controllerError", IAJS.controllerManager)
	},
	
	//event.onChange : new YAHOO.util.CustomEvent("onChange", c),	
	/**
	 * 
	 */
	parse: function(root){
		var nodes, node, i, j, eltype;	
		// find all nodes with attribute eltype
		nodes = IAJS.ELTYPE.get(root);
			  
	  	for(j=0;j<nodes.length;j++) {
			node = nodes[j];
			var eltype = node.getAttribute("eltype");
			var eltypeNs = (eltype.indexOf(":") > -1) ? eltype.split(":") : null;
			try {
				if (eltypeNs == null){
					controllerName = eltype.capitalize().camelize();
					if(typeof IAJS.CONTROLLER[controllerName] == 'undefined'){
						throw new Error("controller not found");
					}
					var controller = new IAJS.CONTROLLER[controllerName](node);
				} else {
					controllerName = eltypeNs[2].capitalize().camelize();
					var controller = new eltypeNs[1][controllerName](node);
				}
				controller.init();// controller must init before adding to controller collection
				IAJS.controllerManager.add(controller);
				//IAJS.formManager.register(controller);
				controller.hookAfterInit();
			} catch(ex) {
				this.event.controllerError.fire({message: ex + " : error on controller init for " + eltype});
			}
	 	}
		/*
		 * let controllers subscribe themself to master 
		 */
		 for(var i in IAJS.controllerCollection) {
		 	IAJS.controllerManager.initMaster(IAJS.controllerCollection[i]);
		 	IAJS.controllerManager.initSubordinate(IAJS.controllerCollection[i]);
		 }
	 },
	/**
	 * Add valid controller to collection
	 * @param {IAJS.CONTROLLER} c The controller to add
	 * @return {boolean} true if succesfull, otherwise false
	 */
	add: function(c){
		//assign controllerId to controller, on fail do not add controller
		if (!c.controllerId && !IAJS.controllerManager.initControllerId(c)) return false;
		//add to collection x
	 	IAJS.controllerCollection[c.controllerId] = c;
	 	IAJS.controllerManager.event.controllerAdd.fire({id : c.controllerId});
	 	return true;
	},
	remove: function(id){
		if (!IAJS.controllerManager.initControllerId(c)) return false;
	},
	/**
	 * Get controller from collection
	 * @return {IAJS.CONTROLLER|null}
	 */
	get: function(id){
 		return (IAJS.controllerCollection) ? IAJS.controllerCollection[id] : false;
	},
	/**
	 * Set master controller and hook into events related to the master controller
	 * @see IAJS.CONTROLLER.BaseController#defaultMasterEvents utility function with list of default master events
	 */
	initMaster: function(c){
		if((master = IAJS.ELATTR.getMaster(c)) && (m = master.controller || master.element)){
			switch (m.action) {
				case 'enable':	
					IAJS.Event.on(m, "onEnableChange", c.onMasterChange, c);
					break;
				case 'valid':
					IAJS.Event.on(m, "validationResultChange", c.onMasterChange, c);
					break;
				case 'change':
					IAJS.Event.on(m, "onChange", c.onMasterChange, c);
					break;
				default:
				try{
					IAJS.Event.on(m, "onChange", c.onMasterChange, c);
					IAJS.Event.on(m, "onEnableChange", c.onMasterChange, c);
					IAJS.Event.on(m, "validationResultChange", c.onMasterChange, c);
					c.onMasterChange(); // force validation based on master on page refresh
					//if(m.events){m.events.fire("onchange");}
				} catch(e){/*console.log("E " +  e)*/}
					break;
			}
		}
		
	},
	/**
  	 * Set subordinate controller and hook into events related to the subordinate controller
  	 * @see #onSubordinateChange
  	 */
  	initSubordinate: function(c){
  		try{
			if(subordinate = IAJS.ELATTR.getSubordinate(c)) {
				var s = IAJS.controllerCollection[subordinate.controller];
				if(s.events){
					var value = s.events.subscribe('onChange', c.onSubordinateChange, c);
				} else{
					// @FIXME remove after all controllers use EventList
					var value = IAJS.Event.on(subordinate.controller, "onChange", c.onSubordinateChange, c);	
				}
				(!value) ? this.event.logEvent.fire("subordinate hook error","error",c) : c.onSubordinateChange(); // force on page refresh	
			}
  		} catch(e){/*console.log(e);*/}
  	},
 
	/**
	 * Called from bootstrap to set master en subordinate controller
	 */
	addListeners: function() {
		IAJS.controllerManager.initMaster();
		IAJS.controllerManager.initSubordinate();
	},
	/**
	 * Should be called only once to assign unique id to controller. A controller can only once recieve an id.
	 * It is possible the function will query the controller for HTMLelement that are assigned to the controller by
	 * the init function of that controller. So the function should only be called during or after the controller has
	 * initialised.
	 * 
	 */
	 initControllerId: function(c){
	 	//if (c.controllerId) return true; //we already have an id
	 	try {
			var key = null;
			//force elattr 
			if (c.node && c.node.getAttribute("elattr") && !c.elattr) c.initAttribute();  
			//
			if (c.elattr && c.elattr.id) key = c.elattr.id;
		 	else if (c.node && c.node.id) key = c.node.id;
		 	else if (c.input &&  c.input.id) key = c.input.id;
		 	else if (c.objectType) key = c.objectType + "_" + IAJS.CONFIG.controllerIdCounter++;
		 	else key = ("controller_" + IAJS.CONFIG.controllerIdCounter++);
		 	//set the id for the controller
		 	c.controllerId = key;
	 	} catch (e) {
	 		this.event.logEvent.fire("failed to created controller id" + e,"error",c, IAJS.RESOURCE.log.INIT);
	 		return false;
	 	}
	 	return true;
	 }
}/**
 * @class IAJS.ELATTR
 * @copyight 2007-2008
 * @version 1.0.5
 */
IAJS.ELATTR = {};
/**
 * Validate format and parse master elattr to object
 * elattr:master format:
 *	 	masterController , masterElement, action
 * 		masterController , masterElement 	(with default eventType)
 * 		masterElement 						(with default eventType, no masterController)
 * @param {IAJS.CONTROLLER} c The controller to get the master value from
 * @return {Object|Boolean} Object(controller:value, element:value, action:value) if succesfull otherwise false
 * @base IAJS.ELATTR 
 */
IAJS.ELATTR.parseMaster = function(c){
	if (c && c.elattr && c.elattr.master && c.elattr.master != ""){
		masterArr = c.elattr.master.split(",");
		if (!masterArr && masterArr.length < 2) return false;
		
		var masterController = (masterArr[1]) ? masterArr[0] : false;
		var masterElement = (masterArr[1]) ? masterArr[1] : masterArr[0];
		var masterAction = masterArr[2] || false;
		return {controller: masterController, element: masterElement, action: masterAction};
	} else {
		return false;
	}
}
/**
 * Parse master elattr part of controller and check presence of master controller in collection
 * @param {IAJS.CONTROLLER} c The controller to get the master value from
 * @return {Object|Boolean} Object(controller:value, element:value) if succesfull otherwise false
 * @base IAJS.ELATTR 
 */
IAJS.ELATTR.getMaster = function(c){
	var master = IAJS.ELATTR.parseMaster(c);
	if (master) {
		if (!IAJS.controllerCollection[master.controller || master.element]){
			IAJS.event.logEvent.fire("elattr:master found but not in controllerCollection","error", c, IAJS.RESOURCE.log.MASTER);
			return false;
		}
	} else {
		return false;
	}
	return master;
}
/**
 * Parse subordinate elattr part of controller
 * @param {IAJS.CONTROLLER} c The controller to parse the subordinate value from
 * @return {Object|Boolean} Object(controller:value, element:value) if succesfull otherwise false
 * @base IAJS.ELATTR 
 */
IAJS.ELATTR.parseSubordinate = function(c){
	if (c && c.elattr && c.elattr.subordinate && c.elattr.subordinate != ""){
		subordinateArr = c.elattr.subordinate.split(",");
		if (!subordinateArr && subordinateArr.length < 2) return false;
		var subordinateController = (subordinateArr[1]) ? subordinateArr[0] : false;
		var subordinateElement = (subordinateArr[1]) ? subordinateArr[1] : subordinateArr[0];
	
		return {controller: subordinateController, element: subordinateElement};
	} else {
		return false;
	}
}
/**
 * Parse subordinate elattr part of controller and check presence of subordinate controller in collection
 * @param {IAJS.CONTROLLER} c The controller to get the subordinate value from
 * @return {Object|Boolean} Object(controller:value, element:value) if succesfull otherwise false
 * @base IAJS.ELATTR 
 */
IAJS.ELATTR.getSubordinate = function(c){
	var subordinate = IAJS.ELATTR.parseSubordinate(c);
	if (subordinate) {
		if (!IAJS.controllerCollection[subordinate.controller]){
			// IAJS.event.logEvent.fire("elattr:subordinate found but not in controllerCollection","error", c, IAJS.RESOURCE.log.SUBORDINATE);
			return false;
		}
	} else {
		return false;
	}
	return subordinate;
}
/**
 * Calculate date range based on date and offset
 * @param date
 * @param diff In forgiving format
 */
IAJS.ELATTR.calcDateDiff = function(date, diff){
	if (!date || !diff) return false;
	if ((/[^0-9|d|m|y]+/).test(diff)) return false; //there should only be legal characters in diff
	var date1 = date.toStructuredDateArray();
	date1 = new Date(date1[2],date1[1],date1[0]); 		
	var date2 = new Date(date1.getTime());
	// parse diff string into usable numbers, null if not match
	var yearsDiff = diff.match(/(\d+)y/);
	var monthsDiff = diff.match(/(\d+)m/);
	var daysDiff = diff.match(/(\d+)d/);	

	if (yearsDiff) date2.setFullYear(date1.getFullYear() + yearsDiff[1]);
	if (monthsDiff) {
		var newMonth = parseInt(date1.getMonth()) + parseInt(monthsDiff[1]);
		var years = 0;

		if (newMonth < 0) {
			while (newMonth < 0) {
				newMonth += 12;
				years -= 1;
			}
		} else if (newMonth > 11) {
			while (newMonth > 11) {
				newMonth -= 12;
				years += 1;
			}
		}				
		date2.setMonth(newMonth);
		date2.setFullYear(date1.getFullYear() + years);		
	}
	if (daysDiff) {
		date2.setDate(date1.getDate() + daysDiff[1]);
	}
	return date2;
}/**
 * @copyight 2007-2008
 * @version 1.0.5
 */
IAJS.ELTYPE = {
    /**
     * Find all HTMLelement that contain the eltype attribute
     * @method getAll 
     * @param {String | HTMLElement} root (optional) The starting point, defaults to document 
     * @return {Array} Array of HTMLelements that contain the eltype attribute
     */
     get:function(root){
            var nodes = [];
            root = (typeof root != 'undefined') ? YAHOO.util.Dom.get(root) : null || document ;
            if (!root) return [];
            
            var elem = root.getElementsByTagName('*');
            for (var i = 0, len = elem.length; i < len; ++i) {
                if (elem[i].getAttribute("eltype")) nodes[nodes.length] = elem[i];
            }

/*alert("nok " + nodes.length);*/

            return nodes;
       }
}/**
 * Controle list af events belonging to a IAJS.CONTROLLER
 * @namespace IAJS
 * @class Event
 * @constructor
 * @copyight 2007-2008
 * @version 1.0.5
 * @property {IAJS.CONTROLLER} c The controller the EventList belongs to 
 */
IAJS.EventList = function(c){
	/**
	 * The events 
	 * @property events
	 * @type YAHOO.util.CustomEvent
	 */
	this.events = [];
	this.controller = c;
};

IAJS.EventList.prototype = {
	/**
	 * Add event to list of events
	 * @methode add
	 * @property {string} type The type of event
	 */
	add: function(type){
		if(!type){
			return false;
		} else {
			this.events.push(new YAHOO.util.CustomEvent(type));
			return true;
		}
	},
	/**
	 * Remove event from list of events
	 * @methode remove
	 * @property {string} type The type of event
	 */
	remove: function(type){
		if(!type){
			return false;
		} else {
			var eventFound = false;
			for(var i=0, l= this.events.length; i < l; ++i){
				var e = this.events[i];
				if(e && e.type == type){
					e.unsubscribeAll();
					this._removeItem(i);
					i = l; // leave for loop	
				}
			}
			return true
		}
	},
	/**
	 * Remove all events from the EventList
	 */
	clear: function() {
		this.events = [];
	},
	/**
	 * Trigger an named event
	 * 
	 * @methode fire
	 */
	fire: function(type, param){
		var param = param || {};
		
		for(var i=0, l=this.events.length; i < l; i++){
			var e = this.events[i];
			if(e && e.type == type){
				param.id = this.controller.controllerId;
				e.fire(param);
				i = l; // leave for loop
			}
		}

	},
	/**
	 * @param {String} 		type		The type of event
	 * @param {Function} 	fn			The function the event will be evaluated
	 * @param {Object}		scope 		The execution scope of the execution event
	 * @return {Boolean}	True 		If successfull, false if unsucsessfull 
	 * @base IAJS.Event
	 */
	subscribe: function(type, fn, scope){
		var e = this._get(type);
		if(e){
			(scope) ? e.subscribe(fn, scope, true) : e.subscribe(fn);
			return true;
		} else {
			return false;
		}
	},
	unsubscribe: function(type, fn){
		var e = this._get(type);
		if(e){
			(scope) ? e.subscribe(fn, scope, true) : e.subscribe(fn);
			return true;
		} else {
			return false;
		}
	},
	/**
	 * 
	 */
	_get:function(type){
		for(var i=0, l = this.events.length; i < l; i++){
			var e = this.events[i];
			if(e && e.type == type){
				return e;
			}
		}
		return false;
	},
	/**
	 * 
	 */
	length: function(){
		return this.events.length;
	},
	/**
	 * 
	 */
	_removeItem: function(index){
		if(index == 0) {
			this.events.shift;
			return;
		}
		
		var l = this.events.length;
		if(index == l){
			this.events.pop;
			return;
		}
		
		this.events.splice(index, 1);
	}
}


IAJS.Event = {}
/**
 * @param {IAJS.CONTROLLER|id} c 	Controller or id that identifies the controller
 * @param {String} 		type		The type of event 
 * @param {Function} 	fn			The function the event will be evaluated
 * @param {Object}		scope 		The execution scope of the execution event
 * @return {Boolean}	True 		If successfull, false if unsucsessfull 
 * @base IAJS.Event
 */
IAJS.Event.on = function(c, type, fn, scope){
	if (!c || !type ) {
		return false;
	}
	/*
	 * check if controller exists & has events
	 */
	var c = (typeof(c) == "object")? c.controllerId : c; // get controller id if IAJS.CONTROLLER is passed
	var events = IAJS.controllerCollection[c].events;
	if(events){	events.subscribe(type, fn, scope);}
}

IAJS.Event.logCustom = function(c){
	if (!c && !c.event) return false;
	for (var key in c.event){
		c.event[key].subscribe(function(e){IAJS.event.logEvent.fire("event." + e + " fired", "warn", c);});
	}	
}
/**
 * @copyight 2007-2008
 * @version 1.0.5
 */
IAJS.formManager = {
	add: function(f, c){
		/*
		 * If form is not present in collection, create form entry.
		 * Then add controller to form, this will the controller into the form custom events
		 */
		if(!IAJS.formCollection[f.id]) IAJS.formCollection[f.id] = new IAJS.CONTROLLER.Form(f).init();
		if(c && c.controllerId) IAJS.formCollection[f.id].register(c);
	},
	/**
	 * Register controller to forms collection
	 * @param {IAJS.CONTROLLER} The controller to resister
	 * @return {Boolean} True if succesful otherwise false 
	 */
	register: function(c){
		/*if(c && c.getCheckInsideForm() &&  c.node){
			var f = IAJS.efw.dom.containingForm(c.node);
			if (f){
				IAJS.formManager.add(f, c);
			} else {
				IAJS.event.logEvent.fire("Could not find form element for controller", "warn", c, IAJS.RESOURCE.log.BOOTSTRAP);
			}
		} else {
			return false;
		}*/
		return true;
	}
}
IAJS.response = {};

IAJS.response.List = function(c){
	this.items = [];
	this.controller = c;
}

IAJS.response.List = {
	
	getDefaultResponse: function(){
		if(! ctrl || ! ctrl.node) return false;
		//
		var item = {indicator: null, response: null, message: ""};
		item.indicator = this._getIndicator;
		item.response =  this._getResponse;
		//
		this.items[this.items.length] = item;
	},
	/**
	 * 
	 */
	_getIndicator : function(){	
		var response = YAHOO.util.Dom.getElementsByClassName('inputFeedback', 'div',this.node);
		return (response.length == 0 )? null : response[0];
	},
	/**
	 * Find HTML element used by the controller to display a response messages
	 * @param {String} input_id the id of the element to find the response element for
	 * @return {HTMLElement | null} A DOM reference to a HTML element or null
	 */
	_getResponse : function(){
		if (!this.node) {return null;}
		var formRow = YAHOO.util.Dom.getAncestorByClassName('formrow', this.node);
		return (YAHOO.lang.isNull(formRow)) ? null : YAHOO.util.Dom.getElementsByClassName('rowFeedback', 'div', formRow);
	},
	/**
	 * 
	 */
	display : function(index){
		var index = (YAHOO.lang.isNumber(index)) ? index : 0;
		var item = this.items[index];
		
		if(item.indicator.hasChildNodes()){ item.indicator.removeChild(item.indicator.firstChild); } 

		var elm = document.createElement('div');
		var msg = c.response ;
		YAHOO.util.Dom.addClass(elm,cls);
		elm.innerHTML = LOCALIZE.messages['FEEDBACK_ERROR'];
		YAHOO.util.Event.addListener(elm, "click", this.setResponseFeedback, msg, true);
		(response.hasChildNodes()) ?	response.replaceChild(elm,response.firstChild) : response.appendChild(elm);
	},
	/**
	 * 
	 */
	confirmation : function(index){
				
	},
	/**
	 * 
	 */
	error : function(index){
		
	},
	/**
	 * 
	 */
	clear : function(){
 		this.items = [];
	}
}
	

IAJS.response.Item = function(c){
	this.controller = c;
	this.indicator = null;		// on error contains clickable error indicator, on confirmation display message 
	this.response = null;		//
	this.noResponseFallback = false;	// indication the no response was found, will route messages to indicator
	this.message = "";
	this.css = {confirmation: 'confirmation', error: 'error', indicator : 'inputFeedback', response : 'rowFeedback', row : 'formrow' };
}

IAJS.response.Item.prototype = {

	confirmation : function(message){
		this._clear();
		
		var elm = document.createElement('div');
		YAHOO.util.Dom.addClass(elm, this.css.confirmation);
		elm.innerHTML = message;
		(this.indicator.hasChildNodes()) ? this.indicator.replaceChild(elm,this.indicator.firstChild) : this.indicator.appendChild(elm);
		/**
		 *  check if own message in response, if so clear
		 */
		if(this.noResponseFallback){
			elm.innerHTML = message;
			(this.indicator.hasChildNodes()) ? this.indicator.replaceChild(elm,this.indicator.firstChild) : this.indicator.appendChild(elm);
		} else {
			if(typeof this.responderIndex != "undefined" && IAJS.responders[this.responderIndex] != false){
				if(this.response.hasChildNodes()){ this.response.removeChild(this.response.firstChild);}
				IAJS.responders[this.responderIndex] = false;				
			}
		} 
	},
	/**
	 * 
	 */
	error : function(message){
		this._clear();
		this.message = message;
		var elm = document.createElement('div');
		YAHOO.util.Dom.addClass(elm, this.css.error);
		if(this.noResponseFallback){
			elm.innerHTML = message;
			(this.indicator.hasChildNodes()) ? this.indicator.replaceChild(elm,this.indicator.firstChild) : this.indicator.appendChild(elm);			
		} else {
			elm.innerHTML = LOCALIZE.messages.FEEDBACK_ERROR;
			YAHOO.util.Event.addListener(elm, "click", this._indicatorClickHandler, this, true);
			(this.indicator.hasChildNodes()) ? this.indicator.replaceChild(elm,this.indicator.firstChild) : this.indicator.appendChild(elm);			
		}

	},
	/**
	 * 
	 */
	 clear : function(){
	 	this._clear();
		if(!this.noResponseFallback){
			if(typeof this.responderIndex != "undefined" && IAJS.responders[this.responderIndex] != false){
				if(this.response.hasChildNodes()){ this.response.removeChild(this.response.firstChild);}
				IAJS.responders[this.responderIndex] = false;				
			}
		} 	 	
	 },
	/**
	 * 
	 */
	_clear : function(){
		/*
		 * clearing of indicator is handled here, clearing of message is done by setting an event in _indicatorClickHandler
		 */
		this.indicator = this.indicator || this._getIndicator();
		this.response = this.response || this._getResponse();
		if(this.indicator.hasChildNodes()){ this.indicator.removeChild(this.indicator.firstChild); } 		
	},
	/**
	 * 
	 */
	_getIndicator : function(){	
		var elm = YAHOO.util.Dom.getElementsByClassName(this.css['indicator'], 'div', this.controller.node);
		return (elm.length == 0 )? null : elm[0];
	},
	/**
	 * Find HTML element used by the controller to display a response messages
	 * @param {String} input_id the id of the element to find the response element for
	 * @return {HTMLElement | null} A DOM reference to a HTML element or null
	 */
	_getResponse : function(){
		var formRow = YAHOO.util.Dom.getAncestorByClassName(this.controller.node, this.css['row']);
		if(YAHOO.lang.isNull(formRow)){
			return null;
		} else {
			var elm = YAHOO.util.Dom.getElementsByClassName(this.css['response'], 'div', formRow);
			if(elm.length == 0){this.noResponseFallback = true;}
			return (elm.length == 0 )? null : elm[0];	
		}
	},
	/**
	 * 
	 */
	_indicatorClickHandler : function(){ 
		var elm = document.createElement('div');
		elm.innerHTML = this.message; 
		YAHOO.util.Dom.addClass(elm, this.css.error);
		if(this.response.hasChildNodes()){ this.response.removeChild(this.response.firstChild);}
		this.response.appendChild(elm);	
		this._setResponder();
	},
	/**
	 * 
	 */
	_setResponder : function(){
		var elm = this.response;
		if(typeof IAJS.responders == "undefined") {IAJS.responders = []};
		// find controller that is using responder
		for(var i=0, l = IAJS.responders.length; i < l; i++){
			if(IAJS.responders[i] == elm){
				IAJS.responders[i] = false;
			}
		}
		// take controle of responder
		if(typeof this.responderIndex == "undefined") {this.responderIndex = IAJS.responders.length};
		IAJS.responders[this.responderIndex] = elm;
	}
}

IAJS.response.Simple = function(c){
	this.controller = c; 
	this.response = false;
	this.message = "";
	this.css = {confirmation: 'confirmation', error: 'error', response : 'inputFeedback', row : 'formrow'};
}

IAJS.response.Simple.prototype = {

	confirmation : function(message){
		this.clear();
		var elm = document.createElement('div');
		YAHOO.util.Dom.addClass(elm, this.css.confirmation);
		elm.innerHTML = message;
		(this.response.hasChildNodes()) ? this.response.replaceChild(elm,this.response.firstChild) : this.response.appendChild(elm);
	},
	/**
	 * 
	 */
	error : function(message){
		this.clear();
		this.message = message;
		var elm = document.createElement('div');
		YAHOO.util.Dom.addClass(elm, this.css.error);
		elm.innerHTML = message;
		(this.response.hasChildNodes()) ? this.response.replaceChild(elm,this.response.firstChild) : this.response.appendChild(elm);
	},
	/**
	 * 
	 */
	clear : function(){
		/*
		 * clearing of indicator is handled here, clearing of message is done by setting an event in _indicatorClickHandler
		 */
		this.response = this.response || this._getResponse();
		if(this.response.hasChildNodes()){ this.response.removeChild(this.response.firstChild); } 		
	},
	/**
	 * 
	 */
	_getResponse : function(){	
		var elm = YAHOO.util.Dom.getElementsByClassName(this.css['response'], 'div', this.controller.node);
		return (elm.length == 0 )? null : elm[0];
	}
}
	
if (YAHOO.widget && YAHOO.widget.Calendar && IAJS.CONFIG.extendYuiCalendar == true ) {
	YAHOO.widget.Calendar.prototype.render = function() {
		this.Style.CCS_NAV_SELECT_MONTH = 'monthselector';
		this.Style.CCS_NAV_SELECT_YEAR = 'yearselector';
	
		this.beforeRenderEvent.fire();
	
		var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG;
		
		// Find starting day of the current month
		var workingDate = YAHOO.widget.DateMath.findMonthStart(this.cfg.getProperty(defCfg.PAGEDATE.key));
	
		this.resetRenderers();
		this.cellDates.length = 0;
	
		YAHOO.util.Event.purgeElement(this.oDomContainer, true);
	
		var html = [];
	
		html[html.length] = '<table cellSpacing="0" class="' + this.Style.CSS_CALENDAR + ' y' + workingDate.getFullYear() + '" id="' + this.id + '">';
		html = this.renderHeader(html);
		html = this.modifyHeader(html);
		html = this.renderSelector(html);
		html = this.renderBody(workingDate, html);
		html = this.renderFooter(html);
		html[html.length] = '</table>';
	
		this.oDomContainer.innerHTML = html.join("\n");
	
		this.applyListeners();
		this.applyListenersSelector();
		this.cells = this.oDomContainer.getElementsByTagName("td");
	
		this.cfg.refireEvent(defCfg.TITLE.key);
		this.cfg.refireEvent(defCfg.CLOSE.key);
		this.cfg.refireEvent(defCfg.IFRAME.key);
	
		this.renderEvent.fire();
	};
	
	YAHOO.widget.Calendar.prototype.modifyHeader = function(html){
		/**
		 * include inline style in table 
		 */
		var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG;
		var workingDate = YAHOO.widget.DateMath.findMonthStart(this.cfg.getProperty(defCfg.PAGEDATE.key));
		html[0] = '<table cellSpacing="0" style="margin-top: 10px;" class="' + this.Style.CSS_CALENDAR + ' y' + workingDate.getFullYear() + '" id="' + this.id + '">';
		/**
		 * 
		 */
		var n = html[5].indexOf(">") + 1;
		html[5] = html[5].substring(0,n) + "previous" + html[5].substring(n);
		html[6] = "&#160;";
		n = html[7].indexOf(">") + 1;
		html[7] = html[7].substring(0,n) + "next" + html[7].substring(n);
		
		return html;
	}
	YAHOO.widget.Calendar.prototype.renderSelector = function(html){
		/**
		 * 
		 */
		var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG;
		var workingDate = YAHOO.widget.DateMath.findMonthStart(this.cfg.getProperty(defCfg.PAGEDATE.key));
		/**
		 * 
		 */
		var monthId = this.id + '_month';
		var monthValue = workingDate.getMonth();	
		var monthFormat = YAHOO.widget.Calendar.LONG;
		var months = this.cfg.getProperty((monthFormat == YAHOO.widget.Calendar.SHORT) ? "MONTHS_SHORT" : "MONTHS_LONG");
		var monthhtml = "";
		
		if (months && months.length > 0) {
			monthhtml = '<select name="' + monthId + '" id="' + monthId + '" class="' + this.Style.CCS_NAV_SELECT_MONTH + '">';
			for (var i = 0; i < months.length; i++) {
				monthhtml += '<option value="' + i + '" ';
				monthhtml += (i == monthValue)? ' selected >' :   '>';
				monthhtml += months[i];
				
				monthhtml += '</option>';
			}
			monthhtml += '</select>';
		}
		/**
		 * 
		 */	
		var yearId = this.id + '_year';
		var yearValue = workingDate.getFullYear();
		var year = '<input type="text" name="' + yearId + '" id="' + yearId + '" class="' + this.Style.CCS_NAV_SELECT_YEAR + '" maxlength="4" size="5" value="'+ yearValue + '" />';
		/**
		 * 
		 */
		html.unshift(year);
		html.unshift(monthhtml);
	
		return html;	
	};
	
	YAHOO.widget.Calendar.prototype.applyListenersSelector = function(e){
		var root = this.oDomContainer;
		var cal = this.parent || this;
		var selectYear = YAHOO.util.Dom.getElementsByClassName(this.Style.CCS_NAV_SELECT_YEAR, 'input', root);
		var selectMonth = YAHOO.util.Dom.getElementsByClassName(this.Style.CCS_NAV_SELECT_MONTH, 'select', root);
		
		YAHOO.util.Event.addListener(selectYear, 'change', cal.selectYear, cal, true);
		YAHOO.util.Event.addListener(selectMonth, 'change', cal.selectMonth, cal, true);
	};
	
	YAHOO.widget.Calendar.prototype.selectMonth = function(e){
		var elt = YAHOO.util.Event.getTarget(e);
		this.setMonth(elt.value);
		this.render();
		this.changePageEvent.fire();
	};
	
	YAHOO.widget.Calendar.prototype.selectYear = function(e){
		var elt = YAHOO.util.Event.getTarget(e);
		this.setYear(elt.value);
		this.render();
		this.changePageEvent.fire();
	};
}/**
 * @copyight 2007-2008
 * @version 1.0.5
 */

/**
 * @param {String} dateString Date as string
 * @param {IAJS.CONFIG.DATE} format The date format to use	 
 */
IAJS.Date = function(dateString,format) {
	// Initialize properties
    this._now = new Date();
	this.monthArray = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	this.format = (format) ? format : false;
	this.dateString = (dateString) ? dateString : "";
	this._date = false;
	/**
	 * Initialization
	 */
	this.init = function() {
		if(this.dateString.toUpperCase() == "NOW") {
			this._date = new Date();
		} else {
			var arr = this._doFormat();
			switch(this.format) {
				case IAJS.CONFIG.dateFormat.iso:
					this._setDate(arr,[2,1,0]);
					break;
				case IAJS.CONFIG.dateFormat.american :
					this._setDate(arr,[1,0,2]);
					break;
				case IAJS.CONFIG.dateFormat.iso :
				default :
					this._setDate(arr,[0,1,2]);
			}
		}
		return this;
	}
	/**
	 * Indication that the date property is set 
	 * @return {Boolean} true is set otherwise false
	 */
	this.isDate = function() {
		return (this._date) ? true : false;
	}
	/**
	 * Indication that the dateSting property is set
	 * @return {Boolean} true is set otherwise false 
	 */
	this.isEmpty = function() {
		return (!this.dateString || this.dateString == "") ? true : false;
	}
	/**
	 * The timestamp value
	 * @return {String} Value as timestamp, 0 if there is no date value
	 */
	this.getTimestamp = function() {
		return (this._date) ? this._date.getTime() : 0;
	}
	/**
	 * The javascript date object property 
	 * @return {Date|Boolean} The date value, otherwise false
	 */		
	this.getDateObject = function() {
		return (this._date) ? this._date : null;
	}
	/**
	 * @return {String|Boolean} The day value, otherwise false
	 */		
	this.getDay = function() {
		return (this._date) ? this._date.getDate() : false;
	}
	/**
	 * @return {String|Boolean} The month value, otherwise false
	 */	
	this.getMonth = function() {
		return (this._date) ? this._date.getMonth()+1 : false;
	}
	/**
	 * @return {String|Boolean} The year value, otherwise false
	 */
	this.getYear = function() {
		return (this._date) ? this._date.getFullYear() : false;
	}
	/**
	 * Add a number of days to the date
	 * @param {String} days The number of days to add
	 * @return {Boolean} True if days where added, otherwise false
	 */
	this.addDay = function(days) {
		if (isNaN(parseInt(days))) return false;
		if(this._date) {
			this._date.setDate(this._date.getDate() + parseInt(days)); 
		}
		return true;
	}
	/**
	 * Compare if date in inbetween range
	 * @param {IAJS.date} minDate 
	 * @param {IAJS.date} maxDate
	 * @return {Boolean|null} True if in range otherwise false,  null if no or invalid parameters are given.
	 */
	this.isInRange = function(minDate,maxDate) {
		var cur = this.getTimestamp();
		if(!minDate && !maxDate) return null;
		if(minDate && maxDate) return (cur < minDate.getTimestamp() || cur > maxDate.getTimestamp());
		if(!maxDate) return (cur < minDate.getTimestamp());
		if(!minDate) return (cur > maxDate.getTimestamp());
	}
	/**
	 * Compare dates
	 * @param {IAJS.date} date The date to compare to.
	 * @return {Boolean|null} true if object date is before date otherwise false, null if date is invalid
	 */
	this.isBefore = function(date){
		//document.write("tt " + date.getTimeStamp());
		if (date === undefined || date === null) return null;
		return (this.getTimestamp() < date.getTimestamp()) ? true : false;
	}
	/**
	 * Compare dates
	 * @param {IAJS.date} date The date to compare to.
	 * @return {Boolean|null} true if object date has equal date otherwise false, null if date is invalid
	 */
	 this.isEqual = function(date){

	 	if (date === undefined || date === null) return null;
	 	return (this.getTimestamp() === date.getTimestamp()) ? true : false;
	 }
	/**
	 * Compare dates
	 * @param {IAJS.date} date The date to compare to.
	 * @return {Boolean|null} true object date is after date otherwise false, null if date is invalid
	 */
	this.isAfter = function(date) {
		if (date === undefined || date === null) return null;
		return (this.getTimestamp() > date.getTimestamp()) ? true : false;
	}
	/**
	 * Format date according to predefined format 
	 * @param {IAJS.CONFIG.DATE} format of the date
	 * @param {String} Value to use to concatenate date
	 * @return {String|null} A formated string or null if invalid
	 */
	this.asFormattedString = function(format,seperator) {
		if(!this._date) return null;
		var format = format || IAJS.CONFIG.defaultDateFormat;
		var sep = (seperator) ? seperator : "-";
		var ret = null;
		switch(format) {
			case IAJS.CONFIG.dateFormat.iso:
				ret = this.getYear() + sep + this.getMonth() + sep + this.getDay();
				break;
			case IAJS.CONFIG.dateFormat.american:
				ret = this.getMonth() + sep + this.getDay() + sep + this.getYear();
				break;
			case IAJS.CONFIG.dateFormat.euro:
				ret = this.getDay() + sep + this.getMonth() + sep + this.getYear();
			default :
				//null
		}
		return ret;
	}
	/**
	 * @param {String} formatString Format of the return value
	 * @return {String}  
	 */
	this.toReadableDate = function(formatString) {
		d = this._date;
		var functions = {
		    DayName: function(d, f){
		        return LOCALIZE.days[f('w')];
		    },
		    MonthName: function(d, f){
		        return LOCALIZE.month[f('n') - 1];
		    }
		}
		return d.format(formatString, functions);
	}
	/**
	 * @private
	 */
	this._setDate = function(arr,sequence) {
		d = (arr[sequence[0]]) ? this._makeDay(arr[sequence[0]]) : false;
		m = (arr[sequence[1]]) ? this._makeMonth(arr[sequence[1]]) : false;
		y = this._makeYear(arr[sequence[2]]);
		if(this._isLeapYear(y)) this.monthArray[1] = 29;
		if(d > this.monthArray[m-1]) d = false;
		this._date = (d && m && y) ? new Date(y,m-1,d) : false;
	}
	/**
	 * @private
	 */	
    this._makeDay = function(str) {
     	if(str.length > 2) return false; // too long
		d = str*1;
		if(d<1 || d>31) return false;
		return d;
	}
	/**
	 * @private
	 */
	this._makeMonth = function(str) {
		if(str.length > 2) return false; // too long
		m = str*1;
		if(m<1 || m>12) return false;
		return m;
	}
	/**
	 * @private
	 * @return
	 */
	this._makeYear = function(str) {
		var year = str || new Date().getUTCFullYear();
		if (year && year.length < 4) year = "2".pad(4-year.length,"0",1) + year;
		return year;
	}
	/**
	 * 
	 * @return {Boolean} true if valid otherwise false
	 */
	this.isValidFormat = function(){
		
	}
	/**
	 * @private
	 * @return {Array}
	 */
	this._doFormat = function() {
    	val = this.dateString.replace(/^[\s]+/, "");	// remove leading spaces
		return val.split(/[\s\.,\/\+_,:=\-]+/); 		// split string : whitespace . / \ + _ , : =
	}
    /**
     * @private
     * @return {Boolean} True if leapyear otherwise false;
     */
	this._isLeapYear = function(y) {
		return (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) ? true : false;
	}
}/**
 * The Response Object
 * 
 * @copyight 2007-2008
 * @version 1.0.5 
 */
function Response(){};
/**
 * clear the reponse tag
 * @param {obj} reponse HtmlElement
 */
Response.clear = function(response)
{
  if(response.hasChildNodes())
	response.removeChild(response.firstChild);
}
/**
 * set the reponse tag
 * @param {obj} reponse HtmlElement
 * @param {string} cls the css class
 * @param {string} msg the message
 */
Response.set = function(response,cls,msg)
{
  Response.clear(response);
  Response.add(response,cls,msg)
}
/**
 * adds a element to the response tag
 * @param {obj} reponse HtmlElement
 * @param {string} cls the css class
 * @param {string} msg the message
 */
Response.add = function(response,cls,msg)
{
  // map class to actual css class
  //if (cls == "error") { cls = "error";}
  // create div or span (combined patterns use span, single patterns use div)
  var elm = document.createElement('div');
  response.msg = msg;
  YAHOO.util.Dom.addClass(elm,cls);
  elm.innerHTML = LOCALIZE.messages['FEEDBACK_ERROR'];
  YAHOO.util.Event.addListener(elm, "click", this.setResponseFeedback, msg, true);
  (response.hasChildNodes()) ?	response.replaceChild(elm,response.firstChild) : response.appendChild(elm);
}

Response.setResponseFeedback = function(type, msg)
{
	var elm = this.getResponseFeedback();
	if(YAHOO.lang.isNull(elm)){
		var newdiv = document.createElement('div');
	}
}

/* * * * * * * * * * * * * * * * * * *
 * HANDLER HELPERS
 * * * * * * * * * * * * * * * * * * */
HandlerHelper = function() {};

HandlerHelper.isInViewport = function(el) {
  var $D = YAHOO.util.Dom;
  var viewportRegion = new YAHOO.util.Region(0,$D.getViewportWidth(),$D.getViewportHeight(),0);
  var elementRegion  = new $D.getRegion(el);
  return viewportRegion.contains(elementRegion);
}
/* * * * * * * * * * * * * * * * * * *
 * STYLE OVERWRITE
 * * * * * * * * * * * * * * * * * * */
document.write('<style>');
document.write('.collapse .box {visibility : hidden; display:none;}');
document.write('.closed .box {visibility : hidden; display:none;}');
document.write('</style>');
/**
 * @fileover Validation helpers 
 * View return values for public functions are set in IAJS.RESPONSE
 * 
 * @version 0.9.2
 */
IAJS.RESPONSE = { 			// standard response codes for all controllers
	OK : 1,					
	INVALID : 2,
	FALLTHROUGH : 4,
	INVALIDFORMAT : 8,
	OUTOFRANGE : 16,
	TOHIGH : 32,
	TOLOW : 64,
	MANDATORY : 128,
	EMPTY : 256
};
IAJS.RESPONSE.TEXT = {		// response codes for textarea controller
	TOLONG : 9
};
IAJS.RESPONSE.NUMBER = {	//response codes for number controller
	NO_FLOAT : 10,
	EXCEED_DECIMAL : 11
};
/**
 * Checks if date is an actual date with optional boundry check
 * 
 * @param {string} date the date to check
 * @param {string} mindate (optional) minimum date, minimum date included 
 * @param {string} maxdate (optional) maximum date, maximum date included
 * @base IAJS.VALIDATION
 * @return {IAJS.RESPONSE} 
 */
IAJS.VALIDATION.date = function(date, mindate, maxdate){
	if(date.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
  	var dateStamp = IAJS.VALIDATION.isDate(date.toStructuredDate());	
  	
  	if (dateStamp == IAJS.RESPONSE.INVALID || isNaN(dateStamp.getTime()))  return IAJS.RESPONSE.INVALID;
  	//if used check minimum date 
	if (mindate != undefined && mindate != "" && mindate != null){
		var minStamp = IAJS.VALIDATION.isDate(mindate.toStructuredDate()); 	
  		var minCompare = (minStamp == IAJS.RESPONSE.INVALID  || isNaN(minStamp.getTime())) ? -2 : dateStamp >= minStamp;
  		if (!minCompare) return IAJS.RESPONSE.TOLOW; 
  	}
  	//if used check maximum date
	if (maxdate != undefined && maxdate != "" && maxdate != null){
		var maxStamp = IAJS.VALIDATION.isDate(maxdate.toStructuredDate());	
  		var maxCompare = (maxStamp == IAJS.RESPONSE.INVALID  || isNaN(maxStamp.getTime())) ? -2 : dateStamp <= maxStamp;
  		if (!maxCompare) return IAJS.RESPONSE.TOHIGH;
  	}
  	return IAJS.RESPONSE.OK;
}
/**
 * @param {String} date 	Date to compare
 * @param {String} dateDiff	The date to compare to
 * @param {String} minDiff	The minimum differnce between the dates
 * @param {String} maxDiff	The maximum differnce between the dates
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.dateDiff = function(date, dateDiff , minDiff, maxDiff){
	if (!date || !dateDiff || !(minDiff || maxDiff)) return IAJS.RESPONSE.FALLTHROUGH; //need at least minDiff or maxDiff
	//convert dates to date object
	var date1 = date.toStructuredDate().toStructuredDateArray();
	var date2 = dateDiff.toStructuredDate().toStructuredDateArray();
	// TODO only calc if needed
	var yearCalc = date1[2] - date2[2];
	var monthCalc = date1[1] - date2[1] + (date1[2] - date2[2])*12 ;	
	var dayCalc = IAJS.VALIDATION.dateDiffCalc(date, dateDiff);
	//
	if(minDiff){
		//there should only be legal characters in minDiff and maxDiff
		if ((/[^0-9|d|m|y]+/).test(minDiff)) return IAJS.RESPONSE.INVALIDFORMAT;
		// parse diff string into usable numbers, null if not match
		var yearsDiff = minDiff.match(/(\d+)y/);
		var monthsDiff = minDiff.match(/(\d+)m/);
		var daysDiff = minDiff.match(/(\d+)d/);
		//
		if (yearsDiff && (yearCalc < yearsDiff[1] )) return IAJS.RESPONSE.TOLOW;
		if (monthsDiff && (monthCalc < monthsDiff[1])) return IAJS.RESPONSE.TOLOW;
		if (daysDiff && (dayCalc < daysDiff[1])) return IAJS.RESPONSE.TOLOW;
	}
	if(maxDiff){
		if ((/[^0-9|d|m|y]+/).test(maxDiff)) return IAJS.RESPONSE.INVALIDFORMAT;
		// parse diff string into usable numbers, null if not match
		var yearsDiff = maxDiff.match(/(\d+)y/);
		var monthsDiff = maxDiff.match(/(\d+)m/);
		var daysDiff = maxDiff.match(/(\d+)d/);	
		//		
		if (yearsDiff && (yearCalc > yearsDiff[1] )) return IAJS.RESPONSE.TOHIGH;
		if (monthsDiff && (monthCalc > monthsDiff[1])) return IAJS.RESPONSE.TOHIGH;
		if (daysDiff && (dayCalc > daysDiff[1])) return IAJS.RESPONSE.TOHIGH;
	} 
	return IAJS.RESPONSE.OK;	
}
/**
 * Calculates the difference between two dates
 * @param {String} date1 Date in format d-m-y
 * @param {String} date2 Date to subtract from date1 (format d-m-y)  
 * @return {String|Boolean} the number of hours between the 2 dates, false if calculation could not compleet
 */
IAJS.VALIDATION.dateDiffCalc = function(date1, date2){
	var date1 = date1.toStructuredDateArray(); 	
	var date2 = date2.toStructuredDateArray();
	date1 = new Date(date1[2],date1[1],date1[0]);
	date2 = new Date(date2[2],date2[1],date2[0]);
	
	var diff = new Date();
	diff.setTime(Math.abs(date1.getTime() - date2.getTime()));
	var days = Math.floor(diff.getTime() / (1000 * 60 * 60 * 24)); 
	return  days;
}
/**
 * Checks if time is an actual 24 hour time with optional boundry check
 * 
 * @param {string} date the date to check
 * @param {string} mintime (optional) minimum time, minimum time included 
 * @param {string} maxtime (optional) maximum time, maximum time included
 * @return {IAJS.RESPONSE} 
 */
IAJS.VALIDATION.time = function(time, mintime, maxtime){
  if(time.length == 0) return IAJS.RESPONSE.FALLTHROUGH;					
  var timeStamp = IAJS.VALIDATION.isTime(time.toStructuredTime());
  if (timeStamp == IAJS.RESPONSE.INVALID || isNaN(timeStamp.getTime())) return IAJS.RESPONSE.INVALID;		
  //if used check minimum time
  if(mintime != undefined && mintime != "" && mintime != null){
		var minStamp = IAJS.VALIDATION.isTime(mintime.toStructuredTime());
		var minCompare = (minStamp == IAJS.RESPONSE.INVALID || isNaN(minStamp.getTime())) ? -2 : timeStamp.getTime() >= minStamp.getTime();	
		if (!minCompare) return IAJS.RESPONSE.OUTOFRANGE;						
  }
  //if used check maximum time
  if(maxtime != undefined && maxtime != "" && maxtime != null){
		var maxStamp = IAJS.VALIDATION.isTime(maxtime.toStructuredTime());
		var maxCompare = (maxStamp == IAJS.RESPONSE.INVALID || isNaN(maxStamp.getTime())) ? -2 : timeStamp.getTime() <= maxStamp.getTime();	
		if (!maxCompare) return IAJS.RESPONSE.OUTOFRANGE;
  }   
  return IAJS.RESPONSE.OK; 													
}
 /**
 * @param {String} time 	time to compare
 * @param {String} timeDiff	The time to compare to
 * @param {String} minDiff	The minimum differnce between the time values
 * @param {String} maxDiff	The maximum differnce between the time values
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.timeRange = function(time, timeDiff , minDiff, maxDiff){
	if (!time || !timeDiff || !(minDiff || maxDiff)) return IAJS.RESPONSE.INVALIDFORMAT; //need at least minDiff or maxDiff
	var t1 = time.toStructuredTime(true);
	var t2 = timeDiff.toStructuredTime(true);
	
	//time - timeDiff as  timestamp
	var diff = Date.UTC(0,0,1,t2[0],t2[1],t2[2],0) - Date.UTC(0,0,1,t1[0],t1[1],t1[2],0);

	if (minDiff){
		//do we need a diff in one direction?
		if (minDiff.charAt(0) == "+" || minDiff.charAt(0) == "-"){
			var t = minDiff.substr(1).toStructuredTime(true);
			var td = Date.UTC(0,0,1,t[0],t[1],t[2],0) - Date.UTC(0,0,1,0,0,0,0);
			if (minDiff.charAt(0) == "+"){
				if (Math.abs(diff) < td || (td - diff) < 0 ) return IAJS.RESPONSE.OUTOFRANGE;	
			} else {
				if (Math.abs(diff) < td  || (td - diff) > 0) return IAJS.RESPONSE.OUTOFRANGE;
			}
		} else {
			//convert minDiff to timestamp
			var t = minDiff.toStructuredTime(true);
			var td = Date.UTC(0,0,1,t[0],t[1],t[2],0) - Date.UTC(0,0,1,0,0,0,0);			
			if (Math.abs(diff) < td) return IAJS.RESPONSE.OUTOFRANGE;
		}
	}
	if (maxDiff){
		//do we need a diff in one direction?
		if (maxDiff.charAt(0) == "+" || maxDiff.charAt(0) == "-"){
			var t = maxDiff.substr(1).toStructuredTime(true);
			var td = Date.UTC(0,0,1,t[0],t[1],t[2],0) - Date.UTC(0,0,1,0,0,0,0);
			if (maxDiff.charAt(0) == "+"){
				if (Math.abs(diff) > td || (td - diff) < 0 ) return IAJS.RESPONSE.OUTOFRANGE;	
			} else {
				if (Math.abs(diff) > td  || (td - diff) > 0) return IAJS.RESPONSE.OUTOFRANGE;
			}
		} else {
			//convert minDiff to timestamp
			var t = maxDiff.toStructuredTime(true);
			var td = Date.UTC(0,0,1,t[0],t[1],t[2],0) - Date.UTC(0,0,1,0,0,0,0);			
			if (Math.abs(diff) < td) return IAJS.RESPONSE.OUTOFRANGE;
		}
	}
	return IAJS.RESPONSE.OK;
}
/**
 * Checks if a email address has a valid format
 * @param {string} email
 * @return {IAJS.RESPONSE}  
 */
IAJS.VALIDATION.email = function(email)
{
  if(email.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
  var val = (/^[-!#$%&\'*+\\.\/0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\.\/0-9=?A-Z^_`a-z{|}~]+$/).test(email);
  return (val) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID;
}
/**
 * Checks if a url has a valid format, a valid url can include a querystring and portnumber
 * @param {String} url the url to validate
 * @param {String} allowedShemes The shemes allowed in url (defaults to http, https, ftp)
 */
IAJS.VALIDATION.url = function(url, allowedShemes)
{
	if(!url || url.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
	var shemes = (allowedShemes) ? allowedShemes.replace(/,\s*/gi, "|") : "https|http|ftp";
	/** 
	* /^(" + shemes + "):\/\/ 	start with sheme from schemes variable followed by semicolumn
	* ([a-z0-9\.]+?)			1 domain with no or more subdomains
	* (\\.[a-zA-Z]{2,6})		top-level domain must start with dot followed by 2 or 6 chracters
	* (\:[0-9]{2,5})?			optional post number example: http://chess.eecs.berkeley.edu:4430/login
	* (\/[a-zA-Z0-9_\?=&;\%\"\.\+-\:]*)	optional trailing query string
	**/
	var checkUrl = new RegExp("^(" + shemes + "):\/\/([a-zA-Z0-9\\.]+?)(\\.[a-zA-Z]{2,3})(\:[0-9]{2,5})?(\/[a-zA-Z0-9_\?=&;\%\"\.\+-\:]*)*$");
	return (checkUrl.test(url))? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID;
}
/**
 * Checks btw/vat format and controle character
 * @param {string} countrycode country iso code, an unknown code will report the btw code as invalid 
 * @param {string} vatcode the vat code to check
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.vat = function(countryCode, vatCode) {
	if( vatCode.length == 0 ) return IAJS.RESPONSE.FALLTHROUGH;								// invalid
	if (countryCode.length == 0 && vatCode.length) return IAJS.RESPONSE.FALLTHROUGH;	// fallthrough (empty
	switch(countryCode) {
		case "BE" :
			return IAJS.VALIDATION.vatBE(vatCode);
			break;
		case "NL" : 
			return IAJS.VALIDATION.vatNL(vatCode);
			break;
		case "UK" :
			return IAJS.VALIDATION.vatGB(vatCode);
			break;
		default:
			return IAJS.RESPONSE.INVALID;												// invalid
	}
}
/**
 * Checks btw/vat format and controle character
 * @param {string} vatcode the vat code to check 
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.vatBE = function(vatCode) {
	vatCode = vatCode.removeSeperators();//remove legal none digit characters: "blank" . -
 	// 10 digits (8 + 2 control)
	// 2 controle digits must equal 97 - first 8 digits % 97	
	if (!(/^(0\d{9}|\d{9})$/).test(vatCode)) return IAJS.RESPONSE.INVALID; // 9  digits or 10 with starting 0
	if (vatCode.length == 9) {
		return (IAJS.VALIDATION.doMod(vatCode.substring(0,7),vatCode.substring(7),97)) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID;;	
	} else {
		return (IAJS.VALIDATION.doMod(vatCode.substring(0,8),vatCode.substring(8),97)) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID;;
	}
	
}
/**
 * Checks btw/vat format and controle character
 * @param {string} vatcode the vat code to check 
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.vatNL = function(vatCode) {
	vatCode = vatCode.removeSeperators();//remove legal none digit characters: "blank" . -
	return IAJS.RESPONSE.FALLTHROUGH;
}
/**
 * Checks btw/vat format and controle character
 * @param {string} vatcode the vat code to check 
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.vatGB = function(vat) {
	/*
	For example, a valid number is 232 1462 05.
	
	The algorithm only applies to the digits within the number;
	The last two digits are the check digit, and should be extracted to a separate field.
	The check digit is calculated as follows:
	Multiply the first 7 digits in turn by 8,7,6....2 then add up the totals as follows:
	2 x 8 = 16
	3 x 7 = 21
	2 x 6 = 12
	1 x 5 = 5
	4 x 4 = 16
	6 x 3 = 18
	2 x 2 = 4
	---------
	        92
	
	Calculate the modulus 97 of the total.
	
	*/
	vat = vat.removeSeperators();//remove legal none digit characters: "blank" . -
	return IAJS.RESPONSE.FALLTHROUGH;
}
/**
 * Checks bankaccount number format and controle character
 * @param {string} countrycode country iso code, an unknown code will report the bankaccount number as invalid 
 * @param {string} bankaccountNumber the vat code to check
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.bankaccount = function(countryCode, bankaccountNumber) {
  	// countrycode or vatcode empty
	if( bankaccountNumber.length == 0 ) return IAJS.RESPONSE.FALLTHROUGH;						// invalid
	if (countryCode.length == 0 && bankCode.length) return IAJS.RESPONSE.FALLTHROUGH;	// fallthrough (empty)

  switch(countryCode) {
     case "BE" :
      	return IAJS.VALIDATION.bankBE(bankaccountNumber);
		break;
	default:
		return IAJS.RESPONSE.FALLTHROUGH;
	}
}
/**
 * @param {String} bankaccountNumber Belgium bank number
 * @return {IAJS.RESPONSE} 
 */
IAJS.VALIDATION.bankBE = function(bankaccountNumber) {
	bankaccountNumber = bankaccountNumber.removeSeperators();//remove legal none digit characters: "blank" . -
	if(!(/^\d{12}$/).test(bankaccountNumber)) return IAJS.RESPONSE.INVALID; // need 12 digits
	var val = IAJS.VALIDATION.doMod(bankaccountNumber.substring(0,10),bankaccountNumber.substring(10),false); 
	return (val) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID ;
}
/**
*
* @param {string} countrycode
* @param {string} phonenumber
* @return {IAJS.RESPONSE}
*/
IAJS.VALIDATION.telephone = function(countryCode , phonenumber)
{
	if (phonenumber.length == 0 || countryCode.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
	switch (countryCode){
		case "BE" :
			return IAJS.VALIDATION.telephoneBE(phonenumber);
		default:
			return IAJS.VALIDATION.telephoneBasic(phonenumber);
	} 
}
/**
* Check Belgium phone number format
* @param {string} phonenumber
* @return {IAJS.RESPONSE}
*/
IAJS.VALIDATION.telephoneBE = function(phonenumber)
{
	if (phonenumber.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
	phonenumber = phonenumber.replace(/^\+/g, ""); 					//remove leading + ;
	phonenumber = phonenumber.replace(/([\\\/\.\-\(\)\s,])/ig, ""); //remove legal none digit characters: "blank", . : - ( ) / \
	var val = (/^[0-9]{3,18}$/).test(phonenumber);					//all remaining characters must be digits, between 3 and 18 
	return (val) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID; 
}
/**
 * Check basic phone number format
 * @param {string} phonenumber
 * @return {IAJS.RESPONSE}
 */
IAJS.VALIDATION.telephoneBasic = function(phonenumber)
{
	if (phonenumber.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
	phonenumber = phonenumber.replace(/^\+/g, ""); 					//remove leading + ;
	phonenumber = phonenumber.replace(/([\\\/\.\-\(\)\s,])/ig, ""); //remove legal none digit characters: "blank", . : - ( ) / \
	var val = (/^[0-9]{3,18}$/).test(phonenumber);					//all remaining characters must be digits, between 3 and 18 
	return (val) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID; 
}
/**
* Check INSZ/NISS format and controle characters
* @param {string} nissCode the INSZ/NISS number to check
* @return {IAJS.RESPONSE.INVALID} (true if the NISS is valid)
*/
IAJS.VALIDATION.niss = function(nissNumber) {
	if (nissNumber.length == 0) return IAJS.RESPONSE.FALLTHROUGH;
	//remove legal none digit characters: "blank" . -
	nissNumber = nissNumber.removeSeperators();
	if (!(/^\d{11}$/).test(nissNumber)) return IAJS.RESPONSE.INVALID; // check if code is 11 characters integer  
	var val = IAJS.VALIDATION.doMod(nissNumber.substring(0,9),nissNumber.substring(9),97); // do mod 97
	return (val) ? IAJS.RESPONSE.OK : IAJS.RESPONSE.INVALID; 
}
/**
 * Checks if a date is valid
 * @param {string} date the date in structured format (31-12-1900 DD-MM-YYYY)
 * @return {IAJS.RESPONSE.INVALID | Date} IAJS.RESPONSE.INVALID if invalid date, date object if valid
 * 
 */
IAJS.VALIDATION.isDate = function(date)
{
  var date_arr = date.split("-");
  var day = date_arr[0];
  var month = date_arr[1];
  var year = date_arr[2];
  // Is month valid ?
  if (month < 1 || month > 12) return IAJS.RESPONSE.INVALID;

  // Is day valid ?
  if (day < 1 || day > 31) return IAJS.RESPONSE.INVALID;

  // Is date valid for month?
  if (month==2) {
		// Check for leap year
		if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
	  	if (day > 29) return IAJS.RESPONSE.INVALID;
		}
		else {
			if (day > 28) return IAJS.RESPONSE.INVALID;
		}
  }
  if ((month==4)||(month==6)||(month==9)||(month==11)) {
		if (day > 30) return IAJS.RESPONSE.INVALID;
  }
  // var newdate=new Date(year,month,day);
  // new Date(year,month,day).getTime()
  return new Date(year,month,day);
}
/**
 * Checks if a time is valid
 * @param {string} time the time in structured format (hh:mm:ss)
 * @return{Date|IAJS.RESPONSE.INVALID} return date object if valid else IAJS.RESPONSE.INVALID 
 */
IAJS.VALIDATION.isTime = function(time)
{
  if (!time || time.length == 0) return IAJS.RESPONSE.INVALID;
  var time_arr = time.split(":");
  var hour = time_arr[0];
  var minute = time_arr[1];
  var second = time_arr[2];
  // Is month valid ?
  if (hour < 0 || hour > 23)
    return IAJS.RESPONSE.INVALID;
  if (minute < 0 || minute > 59)
    return IAJS.RESPONSE.INVALID;
  if (second < 0 || second > 59)
    return IAJS.RESPONSE.INVALID;
  return new Date(1970,1,1,hour,minute,second);
}
/**
 * Checks if string is a number
 * @param {string} number the number to check
 * @param {string} min minimum value of number
 * @param {string} max maximum value of number
 * @param {string} decimals number of decimals allowed
 * @returns {boolean}
 */
 IAJS.VALIDATION.number = function(number, min, max, decimals) {
	if(number.length == 0) return IAJS.RESPONSE.FALLTHROUGH; 
	// there can be a leading - or +
	// there can be one . (dot) or , (comma) at the start of the digits or before the last digit
	number = number.replace(/^\s+/, "");// remove leading spaces
	number = number.replace(/\s+$/, "");// remove trailing spaces
	result = number.match(/^[-|+]?(\d*)([\.|,]?\d+)$/);
	if (result == null) return IAJS.RESPONSE.INVALID;
	// convert string to valid number
	number = number.replace(",", ".");
	number = Number(number);
	if (number == Number.NaN)return IAJS.RESPONSE.INVALID;
	if(min && number < Number(min)) return IAJS.RESPONSE.TOLOW;
	if(max && number > Number(max)) return IAJS.RESPONSE.TOHIGH;
	// result: 
	// 0 = whole match 
	// 1 = before . or , 
	// 2 = after . or , (including . or ,) 
	//
	if (decimals && result.length > 2 && result[2].length -1 > Number(decimals)) {
		return (decimals > 0) ? IAJS.RESPONSE.NUMBER.EXCEED_DECIMAL : IAJS.RESPONSE.NUMBER.NO_FLOAT;
	}
	return IAJS.RESPONSE.OK;
}
/**
 * check 9 number digit with modulus 97
 * @private
 * @param {string} number the number to be checked
 * @param {string} control 
 * @param {string} extractor  
 * @return boolean
 */
IAJS.VALIDATION.doMod = function(number,control,extractor) {
	if(!IAJS.VALIDATION.isInteger(number)) return false;
	if(!IAJS.VALIDATION.isInteger(control)) return false;
	var check = (extractor) ? extractor - number %97 : number%97;
	return (control == check) ? true : false;
};
/**
 * Check if string is an integer
 * @return {boolean} 
 */
IAJS.VALIDATION.isInteger = function(str) {
	return (/^\d+$/).test(str);
};
/**
 * @return int (true , -2 text to long) 
 */
IAJS.VALIDATION.textarea = function(str, maxlength){
	if(!YAHOO.lang.isUndefined(maxlength)){
		return (maxlength && str.length > maxlength) ? IAJS.RESPONSE.TEXT.TOLONG : IAJS.RESPONSE.OK;
	}
	return IAJS.RESPONSE.FALLTHROUGH;
};
if(typeof IAJS.transition == "undefined") {IAJS.transition = function(){}; } 

/**
 * 
 * @argument targetElm 	HTMLElement or id the will recieve the spotlight
 * @argument fromColor	
 * @argument toColor	
 * @argument duration	spotlight duration in seconds
 * @requires IAJS.CONFIG
 * @requires IAJS.EventList
 * 
 */
IAJS.transition.Spotlight = function(targetElm, fromColor, toColor, duration){
	this.objectType = "Spotlight";
	this.targetElm = (typeof targetElm === "object") ? targetElm : document.getElementById(targetElm);
	this.fromColor = fromColor || IAJS.CONFIG.spotlightFromColor ||[255, 255, 255];
	this.toColor = toColor || IAJS.CONFIG.spotlightToColor || [255, 255, 188];
	this.duration = duration || IAJS.CONFIG.spotlightDuration || 1;
	this.anim = false;
	this.events = new IAJS.EventList(this);
	/**
	 * Fires before the spotlight animation starts
	 * @name transitionStart
	 * @memberOf IAJS.transition.Spotlight
	 */
	this.events.add("transitionStart");
	/**
	 * Fires after the spotlight animation stops
	 * @name transitionEnd
	 * @memberOf IAJS.transition.Spotlight
	 */
	this.events.add("transitionEnd");
};


IAJS.transition.Spotlight.prototype = {
	
	setFromColor : function(value){
		this.fromColor = value;
	},
	setToColor : function(value){
		this.toColor = value; 		
	},
	setDuration : function(value){
		this.duration = value;
	},
	/**
	*
	*
	*/
	setTarget : function(value){
		this.targetElm = (typeof value === "object") ? value : document.getElementById(value);
	},
	start : function(){
	 	// on animate if we have a traget
	 	if (typeof this.targetElm == "undefined"){return false;}
		this.events.fire("transitionStart");
		//
		this.bg = YAHOO.util.Dom.getStyle(this.targetElm, "background-color");
	 	// set animation
	 	this.anim = new YAHOO.util.ColorAnim(this.targetElm , {backgroundColor:{to: this.toColor, from: this.fromColor }},this.duration *.5); // use only half of duration because we have 2 animations
		this.anim.iajsController = this;
		//this.anim.parent = this;
		this.anim.onComplete.subscribe(function(){
			// swap from and to colors to reverse animation
			var a = this.attributes.backgroundColor;
			var c = a.to;
			a.to = a.from;
			a.from = c;
			// execute animation
			this.animate();
			// comment next line for nice strobe effect
			this.onComplete.unsubscribeAll();
			this.onComplete.subscribe(
				function(){
					this.iajsController.events.fire("transitionEnd"); 
					this.onComplete.unsubscribeAll();
					YAHOO.util.Dom.setStyle( this.iajsController.targetElm , "background-color", this.iajsController.bg);
					}
			);
		});
		
		this.anim.animate();
	}
}/**
 * @fileoverview The Base Controller
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @param {HTMLelement} node The eltype element to create the controller for 
 */
IAJS.CONTROLLER.BaseController = function(node) {
	/** @type string */
	this.objectType = "BaseController";
	/** @type HTMLelement */
	this.node = node;
	/** @type Array */
	this.input;
	/** @type HTMLelement */
	this.response;
	/** @type Object */
	this.elattr;
	/** @type string */
	this.validationCode;
	/** @type Boolean */
	this.isEnabled;
	
};
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.BaseController.prototype.init = function() {}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.BaseController.prototype.hookAfterInit = function() {}
/**
 * Called before submitting the form this controller belongs to (if any), should be overridden by the subclass
 * @return {IAJS.RESPONSE} validation code
 */
IAJS.CONTROLLER.BaseController.prototype.hookBeforeSubmit = function(o) {
	if(this.elattr && this.elattr.required){
		if (this.validationCode != IAJS.RESPONSE.OK) return false;
	}
	return true;
	
	// if value is empty and field is required, set validationCode to invalid, so it will response with the mandatory error
	if (this.validationCode == IAJS.RESPONSE.FALLTHROUGH && this.elattr && this.elattr.required) {
		this.validationCode = IAJS.RESPONSE.MANDATORY;
		return false;
	}
	return true;
}
/**
 * Validate the data belonging to this controller, should be overridden by the subclasses
 * @return {String} validation code
 */
IAJS.CONTROLLER.BaseController.prototype.validate = function() {
	return IAJS.RESPONSE.INVALID; //validation is handled in subclasses
}
/**
 * Find HTML element used by the controller to indicate a response messages
 * @return {HTMLElement | null} A DOM reference to a HTML element or null
 */
IAJS.CONTROLLER.BaseController.prototype.getResponse = function(){
	if (!this.node) {return null;}
	var response = YAHOO.util.Dom.getElementsByClassName('inputFeedback', 'div',this.node);
	return (response.length == 0 )? null : response[0];
}
/**
 * Find HTML element used by the controller to display a response messages
 * @param {String} input_id the id of the element to find the response element for
 * @return {HTMLElement | null} A DOM reference to a HTML element or null
 */
IAJS.CONTROLLER.BaseController.prototype.getResponseFeedback = function(){
	if (!this.node) {return null;}
	var formRow = YAHOO.util.Dom.getAncestorByClassName('formrow', this.node);
	return (YAHOO.lang.isNull(formRow)) ? null : YAHOO.util.Dom.getElementsByClassName('rowFeedback', 'div', formRow);
}
/**	
 * Create array from elattr properties set in the elattr HTMLelement 
 * Used by sub-class controllers
 *  
 * @private
 */
IAJS.CONTROLLER.BaseController.prototype.initAttribute = function() {
	if(!YAHOO.lang.isObject(this.elattr)) {
		this.elattr = new Object();
		if(this.node){
			attrStr = this.node.getAttribute("elattr");
			if(YAHOO.lang.isString(attrStr)) {
				attrArr = attrStr.split(";");
				if(YAHOO.lang.isArray(attrArr)) {
					for(i=0;i<attrArr.length;i++) {
						if(YAHOO.lang.isString(attrArr[i])) {
							kv = attrArr[i].split(":");
							val = (kv[1] === 'false') ? false : kv[1];
							this.elattr[kv[0]] = (val) ? val : true; // true allows only key with no value like "required" to be added to elattr
						}
					}
				}
			}
		}
	}
}

/**
 * Wrapper to access elattr properties
 * @param {attr} name of the property to return 
 * @return{String|Boolean} current value of the property
 */
IAJS.CONTROLLER.BaseController.prototype.getAttr = function(attr){
	//this.initAttribute();
	//val = eval('this.elattr.' + attr);
	//return (typeof(val) != 'undefined') ? val : false;
	
	return (this.elattr && this.elattr[attr])? this.elattr[attr] : false;
}
/**
 * Wrapper to access elattr properties
 * @param {String} attr	name of property to set
 * @param {String} value to set property to
 */
IAJS.CONTROLLER.BaseController.prototype.setAttr = function(attr,value){
	if (this.elattr) this.elattr[attr] = value;
}
/**
 * Parse elattr attribute of an HTMLelement
 * This could also be used by HTMLelements that have an elattr without eltype 
 * @param {HTMLelement} elm HTMLelement that contains the elattr attribute
 * @return {Array|Boolean}
 */
 IAJS.CONTROLLER.BaseController.prototype.parseAttr = function(elm){
 	if(elm && elm.getAttribute("elattr")){
		attrStr = elm.getAttribute("elattr");
	 	if(YAHOO.lang.isString(attrStr)) {
	 		var attrValue = new Object(); 
			attrArr = attrStr.split(";");
			if(YAHOO.lang.isArray(attrArr)) {
				for(i=0;i<attrArr.length;i++) {
					if(YAHOO.lang.isString(attrArr[i])) {
						kv = attrArr[i].split(":");
						val = (kv[1] === 'false') ? false : kv[1];
						attrValue[kv[0]] = val;
					}
				}
			}
		}
 	}
 	return (attrValue) ? attrValue : false;
 }
/**
 * Indication if controller has its input HTMLelement from and response HTMLelement set.
 * @return {String} Boolean value indicating that the controleer has an input and response element set
 */
IAJS.CONTROLLER.BaseController.prototype.hasResponse = function(){
		return (this.input && this.response);
}
/**
 * Indicate if the controller can be inside a HTML form element 
 * Should be overridden by subclasses
 */
IAJS.CONTROLLER.BaseController.prototype.getCheckInsideForm = function(){return false;}
/**
 * Set enabled state of HTMLelements contained within the controller
 * Could be overridden by subclasses
 * @param {Boolean} value  The enabled state value 
 * @param {Object} args	Used when function is called from custom event
 * @param {Object} me Execution scope when function is called from custom event 
 */
IAJS.CONTROLLER.BaseController.prototype.setEnabled = function(value, args, me){
	//only used when called from custom controller
	if (args){
		 //find out if the elementid of the master elattr is the same as the one passed through args
		 var m = IAJS.ELATTR.getMaster(this);
		 value = (m && m.element == args[0].target)? true : false;  
	}	
	// 
	if (this.input) {
		(value) ? this.input.removeAttribute("disabled") : this.input.setAttribute("disabled","disabled");
	}
	// if subclass has a response element
	if (this.hasResponse){
		if (value) {
			this.validate();
		} else {
			// only remove response if it displays an error  
			if (this.validationCode && this.validationCode != IAJS.RESPONSE.OK){
				Response.clear(this.response);	
			}
		}
	}
	// if the subclass has a enabled property, set the property
	if (this.enabled) this.enabled = value;
	// if the subclass has a onEnableChange event, fire event
	if (this.events) {this.events.fire('onEnableChange')};
}
/**
 * Handler for calling setEnable function in subclasses with a boolean
 * property based on the HTMLelement
 * 
 */
IAJS.CONTROLLER.BaseController.prototype.enabledHandler = function(e){
	var elm = YAHOO.event.getTarget(e);
	this.setEnabled(elm.checked);
}
/**
 * Handle onChange event from subordinate controller
 * @see #setSubordinate
 */
IAJS.CONTROLLER.BaseController.prototype.onSubordinateChange = function() {return false;}
/**
 * Handle onChange event from master controller
 * @see #setMaster
 */
IAJS.CONTROLLER.BaseController.prototype.onMasterChange = function() {
	this.validate();
}
/**
 * Initialize controller events
 * @private
 */
IAJS.CONTROLLER.BaseController.prototype._initEvent = function(){return false;}
/**
 * Initialization of default events related to controllers that can act as a master to other controllers.
 * Called from subclasses 
 * @static
 */
IAJS.CONTROLLER.BaseController.defaultMasterEvents = function(c){
	c.event = c.event || {};
	c.event.onChange = new YAHOO.util.CustomEvent("onChange", c);
	c.event.onEnableChange = new YAHOO.util.CustomEvent("onEnableChange", c);
	c.event.validationResultChange = new YAHOO.util.CustomEvent("validationResultChange", c);
	c.event.validate = new YAHOO.util.CustomEvent("validate", c);
	c.event.logEvent = new YAHOO.util.CustomEvent("logEvent", c);
	c.event.initialize = new YAHOO.util.CustomEvent("initialize", c);
}
/**
 * @fileoverview The DefinitionList Base
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.DefinitionListBase = function(node) {
	this.node = node;
	this.deflistName;
	this.deftextnode;
	this.floater;
	this.objectType = "DefinitionListBase";
	this.css = {controls: 'controls', definitionList : 'defList'};
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the controller is shown.
	 * @name show
	 * @memberOf IAJS.CONTROLLER.DefinitionListBase
	 */	
	this.events.add("show");
	/**
	 * Fires after the controller is hidden.
	 * @name hide
	 * @memberOf IAJS.CONTROLLER.DefinitionListBase
	 */	
	this.events.add("hide");	
}
/**
 * @private
 */
function DefListWorld() { 
	this.showEvent = new YAHOO.util.CustomEvent("showEvent", this);
}
var world = new DefListWorld();

YAHOO.extend(IAJS.CONTROLLER.DefinitionListBase, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.DefinitionListBase.prototype.init = function(deflistName) {
    this.deflistName = deflistName;
	
	if (this.node) {
	  // hide definition lists
	  this.deflists = YAHOO.util.Dom.getElementsByClassName(this.deflistName, "div")[0];
	  YAHOO.util.Dom.addClass(this.deflists, "hidden");
	  // extract our definition
	  var defid = this.node.getAttribute('href').substring(1);
	  var deflink = document.getElementById(defid);
	  
	  if (deflink) {
	  	this.deftextnode = null;
	  	var name = "#" + this.node.id;
	  	var elm = YAHOO.util.Dom.getElementsBy(function(){return true}, 'dd', deflink.parentNode);
	  	for(var i=0, l = elm.length; i < l; i++){
	  		var backlinks = YAHOO.util.Dom.getElementsBy(function(el) { return el.href.indexOf(name) > -1;},"a",elm[i]);
	  		if(backlinks.length > 0){
	  			this.deftextnode = elm[i];
	  			YAHOO.util.Dom.batch(backlinks, function(el){YAHOO.util.Dom.setStyle(el,"display","none");});
	  			i = l; // found what we were looking for, leave for loop
	  		} 
	  	}
	  }
	  // add click event to term
	  YAHOO.util.Event.on(this.node, "click", this.show, this, true);
	  YAHOO.util.Event.on(this.node, "click", this.doNothing, this, true);

      // listen for show event in our world
      this.world = world;
      this.world.showEvent.subscribe(this.onShowEvent, this);
	}
}
/**
 * @private
 */
IAJS.CONTROLLER.DefinitionListBase.prototype.onShowEvent = function(type, floater, me) {
    // check if our floater is visible, if it is then we hide ourselves
    if (YAHOO.util.Dom.getStyle(me.floater,"visibility") == "visible") {
		// hide!
		YAHOO.util.Dom.setStyle(me.floater,"visibility","hidden");
		
		// add show handlers
		YAHOO.util.Event.on(me.node, "click", me.show, me, true);
		
		// remove hide handlers
		YAHOO.util.Event.removeListener(document, "keyup", me.hide);
		YAHOO.util.Event.removeListener(document, "click", me.hide);
    }
}
/**
 * Make sure that we never trigger the default event
 * @private
 */
IAJS.CONTROLLER.DefinitionListBase.prototype.doNothing = function(e) {
    // just to make sure that we never trigger the default event
    // this is necessarry because we remove the show handler on show (we add it back on hide)
    YAHOO.util.Event.stopEvent(e);
}
/**
 * Display the definition list
 */
IAJS.CONTROLLER.DefinitionListBase.prototype.show = function(e) {
	/* the floater will be shown under these circumstances:
	   - click event on this.node
	*/
	var elt = YAHOO.util.Event.getTarget(e);
	// calculate default position
	var reg = YAHOO.util.Dom.getRegion(elt);
	var x = YAHOO.util.Dom.getX(elt);
	var y = YAHOO.util.Dom.getY(elt) + (reg.bottom - reg.top);
	var imgX = 14;
	var imgY = 7;
	// move !
	YAHOO.util.Dom.setXY(this.floater,[x-imgX,y+imgY]);
	//reposition
	
	//if (!HandlerHelper.isInViewport(this.floater)) {
	  var $D = YAHOO.util.Dom;
	  var elt = YAHOO.util.Event.getTarget(e);
	  // reposition
	  var viewportRegion = new YAHOO.util.Region(0,$D.getViewportWidth(),$D.getViewportHeight(),0);

	  // the floater
	  var floatRegion  = new $D.getRegion(this.floater);
	  var width = floatRegion.right - floatRegion.left;
	  var height = floatRegion.bottom - floatRegion.top;

	  // the target element
	  var eltReg = YAHOO.util.Dom.getRegion(elt);
	  var eltX = YAHOO.util.Dom.getX(elt);
	  var eltY = YAHOO.util.Dom.getY(elt) + (eltReg.bottom - eltReg.top);
	  
	  // topleft
	  if (floatRegion.right < viewportRegion.right && floatRegion.bottom < viewportRegion.bottom) {
	  	if(this["hookOnTopLeft"]) this.hookOnTopLeft();
	  }
	  
	  YAHOO.util.Dom.addClass(this.speechBubble,"tl");
	  // topright
	  if (floatRegion.right > viewportRegion.right && floatRegion.bottom < viewportRegion.bottom) {
		var x = eltX - width + (eltReg.right - eltReg.left);
		var y = eltY;
		$D.setXY(this.floater,[x,y]);
		if(this["hookOnTopRight"]) this.hookOnTopRight();
	  }
	  // bottomright
	  if (floatRegion.right > viewportRegion.right && floatRegion.bottom > viewportRegion.bottom) {
		var x = eltX - width + (eltReg.right - eltReg.left);
		var y = eltY - height - (eltReg.bottom - eltReg.top);
		$D.setXY(this.floater,[x,y]);
		
		if(this["hookOnBottomRight"]) this.hookOnBottomRight();
	  }
	  // bottomleft
	  if (floatRegion.right < viewportRegion.right && floatRegion.bottom > viewportRegion.bottom) {
		var x = eltX -imgX;
		var y = eltY - height - (eltReg.bottom - eltReg.top) -imgY;
		$D.setXY(this.floater,[x,y]);
		if(this["hookOnBottomLeft"]) this.hookOnBottomLeft();
	  }
	//}

    // tell the world that we are going to show ourselves, so that they can hide themselves
    this.world.showEvent.fire(this.floater);

	// make ourselves visibility
	YAHOO.util.Dom.setStyle(this.floater,"visibility","visible");

	// add hide handlers
	YAHOO.util.Event.on(document, "keyup", this.hide, this, true); // to handle escape key
	YAHOO.util.Event.on(document, "click", this.hide, this, true); // to handle "click away"

    // remove show handlers
	YAHOO.util.Event.removeListener(this.node, "click", this.show);

	// stop default event
	YAHOO.util.Event.stopEvent(e);
	
	// trigger custom controller event
	this.events.fire("show");	
}
/**
 * Hide the definition list
 */
IAJS.CONTROLLER.DefinitionListBase.prototype.hide = function(e) {
	/* the floater must be hidden under these circumstances:
	   - the escape key is pressed
	   - a click anywhere on the screen
	   - onblur when not blurring to the related input field -> FIXME: not implemented
	*/
	var elt = YAHOO.util.Event.getTarget(e);
    if (elt && (elt.parentNode == this.floater || elt == this.floater)) {
      // we will not hide when our floater has been clicked
      return;
	}
	if (e.type == "keyup") {
	  if( YAHOO.util.Event.getCharCode(e) == 27 ) { // escape
		YAHOO.util.Dom.setStyle(this.floater,"visibility","hidden");
	  } else {
        // floater is only hidden when pressing escape.
        // for other keys we pretend nothing happened -> return
		return;
      }
    } else if (elt && elt.type == "text") {
		// FIXME: this is a hack... we can not assume "text" input field ??
        // FIXME: check if the input field is "our" related input field.
        // special case where the click event happened on an input field -> don't hide floater
		return;
	} else {
	  YAHOO.util.Dom.setStyle(this.floater,"visibility","hidden");
	}
	
    // add show handlers
	YAHOO.util.Event.on(this.node, "click", this.show, this, true);

	// remove hide handlers
	YAHOO.util.Event.removeListener(document, "keyup", this.hide);
	YAHOO.util.Event.removeListener(document, "click", this.hide);
	
	// trigger custom controller event
	this.events.fire("hide");		
}
/**
 * The TelephoneBase Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */ 
IAJS.CONTROLLER.TelephoneBase = function(node) {
	this.node = node;
	this.objectType = "TelephoneBase";	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.TelephoneBase
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.TelephoneBase
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.TelephoneBase
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.DateTelephoneBase
	 */	
	this.events.add("validate");	
}

YAHOO.extend(IAJS.CONTROLLER.TelephoneBase, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.TelephoneBase.prototype.init = function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
		this.initAttribute();
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
}
/**
 * return country property, should be overridden by subclasses 
 */
IAJS.CONTROLLER.TelephoneBase.prototype.getCountry = function() {};
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.TelephoneBase.prototype.hookAfterInit = function() {
	this.validate();
}
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.TelephoneBase.prototype.validate = function() {
	this.validationCode = IAJS.VALIDATION.telephone(this.getCountry(), this.input.value);
	this.responseAction();
}
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.TelephoneBase.prototype.responseAction = function() {
	switch(this.validationCode) {
	  	case IAJS.RESPONSE.OK:
			this.responseItem.confirmation(this.input.value.toReadablePhone());
			break;
	  	case IAJS.RESPONSE.INVALID:
			this.responseItem.error(LOCALIZE.messages.PHONE_INVALID);
			break;
	  	case IAJS.RESPONSE.FALLTHROUGH:
	  	default:
			this.responseItem.clear();
	}
}
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.TelephoneBase.prototype.getCheckInsideForm = function(){return true;}
/**
 * The VAT Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for.
 */

IAJS.CONTROLLER.VatBase = function(node) {
	this.node = node;
	this.insideForm = true;
	this.objectType = "VatBase";
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.VatBase
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.VatBase
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.VatBase
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.VatBase
	 */	
	this.events.add("validate");
};

YAHOO.extend(IAJS.CONTROLLER.VatBase, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.VatBase.prototype.init = function(node) {
	this.node = node;
	if(this.node) {
		this.input = YAHOO.util.Dom.getElementsByClassName("textfield","input",this.node)[0];		
		this.initAttribute();
		this.response = this.getResponse(this.input.id);
		if (this.hasResponse()) {
			YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
		}			
	}
};
/**
 * return country property, should be overridden by sub classes 
 */
IAJS.CONTROLLER.VatBase.prototype.getCountry = function() {};
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.VatBase.prototype.hookAfterInit = function() {
	 this.validate();
};
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.VatBase.prototype.validate = function() {
	var v = this.validationCode;
	this.validationCode = IAJS.VALIDATION.vat(this.getCountry(),this.input.value);
	this.events.fire('validate');
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;	
};
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.VatBase.prototype.responseAction = function() {
		switch(this.validationCode) {
			case IAJS.RESPONSE.OK:
				Response.clear(this.response);
				break;
			case IAJS.RESPONSE.INVALID:
				Response.set(this.response,"error",LOCALIZE.messages.VAT_INVALID);
				break;
			case IAJS.RESPONSE.FALLTHROUGH:
			default:
				Response.clear(this.response);
		}
};

/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.VatBase.prototype.getCheckInsideForm = function(){return true;};
/**
 * @fileoverview The Beban Controller, Belgian Bank Account Number
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * 
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */	
IAJS.CONTROLLER.Beban = function(node) {
	this.objectType = "Beban";
	this.node = node;
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Beban
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Beban
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Beban
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Beban
	 */	
	this.events.add("validate");
}

YAHOO.extend(IAJS.CONTROLLER.Beban, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Beban.prototype.init = function() {
	//
	if(this.node) {
		this.input = YAHOO.util.Dom.getElementsByClassName("textfield","input",this.node)[0];
		this.response = this.getResponse(this.input.id);
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
		YAHOO.util.Event.on(this.country, "change", this.validate, this, true);
	}
}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Beban.prototype.hookAfterInit = function() {
	 this.validate();
}
/**
 * Validate the data belonging to this controller.
 * Triggers onValidate event and validationResultChange event the validation value changed
 */
IAJS.CONTROLLER.Beban.prototype.validate = function() {
	var v = this.validationCode;
	this.events.fire("validate");
	this.validationCode = IAJS.VALIDATION.bankaccount('BE', this.input.value);
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire("validationResultChange");
}
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.Beban.prototype.responseAction = function() {
	switch(this.validationCode) {
		case IAJS.RESPONSE.OK:
			Response.clear(this.response);
			break;
		case IAJS.RESPONSE.INVALID: 
			Response.set(this.response,"error",LOCALIZE.messages.BANKACCOUNT_INVALID);
			break;
		case IAJS.RESPONSE.FALLTHROUGH:
		default:
			Response.clear(this.response);
	}
}
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Beban.prototype.getCheckInsideForm = function(){return true;}/**
 * @fileoverview The Checkbox Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Checkbox = function(node,owner) {
		this.node = node;
		this.owner = owner;
		this.isSelected = false;
		this.objectType = "Checkbox";
		this.events = new IAJS.EventList(this);
		/**
		 * Fires after the value is changed.
		 * @name onChange
		 * @memberOf IAJS.CONTROLLER.Checkbox
		 */	
		this.events.add("onChange");
		/**
		 * Fires after the controller is enable state is changed.
		 * @name contentChange
		 * @memberOf IAJS.CONTROLLER.Checkbox
		 */	
		this.events.add("onEnableChange");
		/**
		 * Fires after the value is validated
		 * @name validate
		 * @memberOf IAJS.CONTROLLER.Checkbox
		 */	
		this.events.add("validate");
};

YAHOO.extend(IAJS.CONTROLLER.Checkbox, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Checkbox.prototype.init = function() {
	if (this.node) {
		this.id = this.node.getAttribute("id");
		YAHOO.util.Event.on(this.id, "click", this.owner.select, this, this.owner);
	}
	return this;
};
/**
 * 
 */
IAJS.CONTROLLER.Checkbox.prototype.select = function() {
	this.isSelected = this.node.checked;
	this.events.fire("onChange");
}
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Checkbox.prototype.validate = function() {
	this.events.fire('validate');
	return false;
};
/**
 * Set response based on validation code
 */	
IAJS.CONTROLLER.Checkbox.prototype.responseAction = function() {
	return false;
};
/**
 * @fileoverview The Checkboxlist Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Checkboxlist = function(node) {
	IAJS.CONTROLLER.Checkboxlist.superclass.constructor.call(this, node);
	this.node = node;
	this.objectType = "Checkboxlist";
	this.group = new Object;
	this.id;
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Checkboxlist
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Checkboxlist
	 */	
	this.events.add("onEnableChange");
};

YAHOO.extend(IAJS.CONTROLLER.Checkboxlist, IAJS.CONTROLLER.BaseController);

/**
 * Initialization of the controller
 * @return {Boolean} True if initialization was successful otherwise false
 */
IAJS.CONTROLLER.Checkboxlist.prototype.init = function() {
	// 
	this.initAttribute(); 
	//
	var id = (this.elattr && this.elattr.id) ? this.elattr.id : false; 
	
	var rows = YAHOO.util.Dom.getElementsBy(function(el){ return (el.getAttribute("type") == "checkbox")}, "input", this.node);
	if(rows) {
		for(i=0;i<rows.length;i++) {
			node = rows[i];
			nodeId = node.getAttribute("id");
			if(nodeId.substring(0,id.length) == id) {
				this.group[nodeId] = new IAJS.CONTROLLER.Radio(node,this).init();
			}
		}
		for(var i in this.group) {
			this.select(false,this.group[i]);
		}
	}
};

IAJS.CONTROLLER.Checkboxlist.prototype.hookAfterInit = function() {return false};
IAJS.CONTROLLER.Checkboxlist.prototype.hookBeforeSubmit = function() {
	return false;
};
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Checkboxlist.prototype.validate = function() {
	//this.responseAction();
};
/**
 * Onclick event from subscribed checkbox
 */	
IAJS.CONTROLLER.Checkboxlist.prototype.select = function(e,obj) {
	this.group[obj.id].select();
	this.events.fire('onChange');
}
/**
 * 
 */
IAJS.CONTROLLER.Checkboxlist.prototype.getSelected = function() {
	var selected = {};
	for(key in this.group) selected[key] = this.group[key].isSelected;
	return selected;
}
/**
 * @fileoverview The Date Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 * 
 * @title Date
 * @namespace IAJS.CONTROLLER
 * @requires IAJS.CONTROLLER.baseController, 
 * @description <p>elattr=&quote;mindate:01-01-2007;maxdate:01-08-2007&quote;
 * 
 * </p>
 *
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Date = function(node) {
	IAJS.CONTROLLER.Date.superclass.constructor.call(this, node);
	this.objectType = "Date";
	this.node = node;
	this.datePickerNode;
	this.id;
	this.date = null;
	this.dateFormat = IAJS.CONFIG.defaultDateFormat;
	this.css = {controls: 'controls', datepicker: 'datepickerIcon'};
	this.responseItem = new IAJS.response.Item(this);
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Date
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Date
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Date
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Date
	 */	
	this.events.add("validate");
}
 
YAHOO.extend(IAJS.CONTROLLER.Date, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 * @param {HTMLelement} input Set input to this element instead of using DOM hierarchy, used if node and input are the same (optional) 
 * @return {Boolean} True if initialization was successful otherwise false
 */
IAJS.CONTROLLER.Date.prototype.init = function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
		this.initAttribute();
		/**
		 * 
		 */
		if(this.input) {
			this.id = this.input.id;
			if(this.elattr.format) this.dateFormat = this.elattr.format;
			this.date = new IAJS.Date(this.input.value,this.dateFormat).init();
			
			this.datePickerNode = YAHOO.util.Dom.getElementsByClassName(this.css['datepicker'],'span', this.node)[0];
			if (typeof this.datePickerNode !=  'undefined'){
				this.datepicker = new IAJS.CONTROLLER.DatePicker(this);
				this.datepicker.init();	
			}
		}		
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
}
/**
 * Set value of date property
 * @param {String} date date to set controller to, day-month-year
 */
IAJS.CONTROLLER.Date.prototype.setDate = function(date) {
	this.input.value = date;
	this.validate();
}

/**
 * Set the focus the the HTMLelement of this controller
 */
IAJS.CONTROLLER.Date.prototype.focus = function() {
	this.input.focus();
}
/**
 * Retrieve the date property
 * @return {String} value of the date 
 */
IAJS.CONTROLLER.Date.prototype.getDate = function() {
	 return (this.date) ? this.input.value : false;
}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Date.prototype.hookAfterInit = function() {
    this.validate();
}
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.Date.prototype.validate = function() {
	var v = this.validationCode;
	this.validationCode = this._validate();
	this.events.fire('validate');
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange', this.validationCode);
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;
}

IAJS.CONTROLLER.Date.prototype._validate = function() {
	this.date = new IAJS.Date(this.input.value,this.dateFormat).init();
	if(this.date.isEmpty()) return IAJS.RESPONSE.FALLTHROUGH; 
	if(!this.date.isDate()) return IAJS.RESPONSE.INVALID;
	var mindate = false;
	var maxdate = false;
	var dif = false;
	var m = IAJS.ELATTR.getMaster(this);
	if(m) {
		var master = (m.controller) ? IAJS.controllerCollection[m.controller] : IAJS.controllerCollection[m.element];
		if(master.validationCode == IAJS.RESPONSE.OK) {
			//maxdate = new IAJS.Date(this.master.date.asFormattedString(),this.dateFormat).init();
			var nr = this.elattr.diff;
			var prefix = nr.substring(0,1);
			if(prefix == "-") {
				mindate = new IAJS.Date(master.date.asFormattedString(),this.dateFormat).init();
				mindate.addDay(nr*1);
			}
			else if(prefix == "+") {
				maxdate = new IAJS.Date(master.date.asFormattedString(),this.dateFormat).init();
				maxdate.addDay(nr*1);
			}
			else {
				nr = nr*1;
				mindate = new IAJS.Date(master.date.asFormattedString(),this.dateFormat).init();
				mindate.addDay(-nr);
				maxdate = new IAJS.Date(master.date.asFormattedString(),this.dateFormat).init();
				maxdate.addDay(nr);
			}
			dif = true;
		}
	} else {
		if (this.elattr.mindate) mindate = new IAJS.Date(this.elattr.mindate).init();
		if (this.elattr.maxdate) maxdate =  new IAJS.Date(this.elattr.maxdate).init();
	}
	if(dif) {
		if(!this.date.isInRange(mindate,maxdate)) return IAJS.RESPONSE.OUTOFRANGE;
	}
	else {
		if(mindate) {
			if(this.date.isBefore(mindate)) return IAJS.RESPONSE.TOLOW;
		}
		if(maxdate) {
			if(this.date.isAfter(maxdate)) return IAJS.RESPONSE.TOHIGH;
		}
	}
	return IAJS.RESPONSE.OK;
}

/**
 * Set response based on validation code, should be overridden by subclasses
 */
IAJS.CONTROLLER.Date.prototype.responseAction = function() {
	switch(this.validationCode) {
	  case IAJS.RESPONSE.OK:
		this.responseItem.confirmation(this.date.toReadableDate("%DayName% %j% %MonthName% %Y%"));
		break;
	  case IAJS.RESPONSE.INVALID:
	  	this.responseItem.error(LOCALIZE.messages.DATE_INVALID);
		break;
	  case IAJS.RESPONSE.OUTOFRANGE : case IAJS.RESPONSE.TOHIGH : case IAJS.RESPONSE.TOLOW :
		this.responseItem.error(this.date.toReadableDate("%DayName% %j% %MonthName% %Y%") + " " + LOCALIZE.messages.DATE_OUT_OF_RANGE);
		break;
      case IAJS.RESPONSE.MANDATORY:
		this.responseItem.error(LOCALIZE.messages.DATE_MANDATORY);
        break;
	  case IAJS.RESPONSE.FALLTHROUGH:
	  default:
		this.responseItem.clear();
	}	
}
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Date.prototype.getCheckInsideForm = function(){return true;}
/**
 * Set enabled state of HTMLelements contained within the controller
 * @param {Boolean} value  The enabled state value 
 */
IAJS.CONTROLLER.Date.prototype.setEnabled = function(value){
	IAJS.CONTROLLER.Date.superclass.setEnabled.call(this, value);
	if(this.datepicker)this.datepicker.setEnabled(value);
}
/**
 * 
 */
IAJS.CONTROLLER.Date.prototype.onSubordinateChange = function(){
	var subordinate = IAJS.ELATTR.getSubordinate(this);
	if(subordinate)	{
		var selected = IAJS.controllerCollection[subordinate.controller].getSelected();
		if (selected) this.setEnabled(selected[subordinate.element]);
	}
}

/**
 * Fires after the tab content is changed.
 * <p><strong>Event fields:</strong><br>
 * <code>&lt;String&gt; type</code> contentChange<br>
 * <code>&lt;String&gt;
 * prevValue</code> the previous value<br>
 * <code>&lt;Boolean&gt;
 * newValue</code> the updated value</p>
 * <p><strong>Usage:</strong><br>
 * <code>var handler = function(e) {var previous = e.prevValue};<br>
 * myTabs.addListener('contentChange', handler);</code></p>
 * @name contentChange
 * @memberOf IAJS.CONTROLLER.Date
 */

/**
 * @name contentChangeMe
 * @event onEnableChange controller has been enabled or disabled
 * @event {object} onChange row element has changed value
 * Fires after the tab content is changed.
 * <p><strong>Event fields:</strong><br>
 * <code>&lt;String&gt; type</code> contentChange<br>
 * <code>&lt;String&gt; prevValue</code> the previous value<br>
 * <code>&lt;Boolean&gt; newValue</code> the updated value</p>
 * <p><strong>Usage:</strong><br>
 * <code>var handler = function(e) {var previous = e.prevValue};<br>
 * myTabs.addListener('contentChange', handler);</code></p>
 * @event {object} validationResultChange 
 * validation state has changed	 qsdfsdfqsdf
 * regel2 qsdfsdf
 * regel3 sdsqdfsdfnjkljmljmlkjdsfqsdf
 * @memberOf IAJS.CONTROLLER.Date
 * @eltype {string} date
 * @elattr {string} mindate a minimum date
 * @elattr {string} maxdate a maximum date
 *//**
 * @fileoverview The DatePicker
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @param {IAJS.CONTROLLER.Date} owner The Date controller to create the controller for
 */
IAJS.CONTROLLER.DatePicker = function(owner) {
	this.node = null;
	this.id = null;		
	this.owner = owner;	// IAJS.CONTROLLER.date that owns the datepicker
	this.calendar;		// YAHOO.widget.Calendar
	this.calendarImg;	// image that will get click event
	this.calendarDiv;	// placeholder for the calendar
	this.visible = false;
	this.enabled = true;
	this.objectType = "DatePicker";
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.DatePicker
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.DatePicker
	 */	
	this.events.add("onEnableChange");
}

/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.DatePicker.prototype.init = function() {
	this.node = this.owner.datePickerNode;
	this.id = this.owner.id;
	
	this._createPickerImage();
	// set click event
	YAHOO.util.Event.on(this.calendarA.getAttribute('id'), "click", this.show, this, true);
	YAHOO.util.Event.on(this.calendarA.getAttribute('id'), "click", this.doNothing, this, true);
	// listen for show event in our world
	this.world = IAJS.OBSERVER.getInstance();
	this.world.subscribe(this.onShowEvent, this, true);
}

/**
 * Create date picker image, called from init.
 * @private
 */
IAJS.CONTROLLER.DatePicker.prototype._createPickerImage = function() {
	//create picker image
	this.calendarA = document.createElement('A');
	this.calendarA.setAttribute("href","javascript:void(0)");
	this.calendarA.setAttribute("id", "datepickerControl_" + (this.owner.id));
	this.calendarA.setAttribute("alt", LOCALIZE.translation.DATEPICKER);
	YAHOO.util.Dom.addClass(this.calendarA, 'action field');
	
	/* 
	calendarText = document.createTextNode(LOCALIZE.translation.DATEPICKER);
	this.calendarA.appendChild(calendarText);
	*/
	this.calendarImg = document.createElement('IMG');
	this.calendarImg.setAttribute("src", IAJS.CONFIG['datepickerImage']);
	this.calendarImg.setAttribute("alt", LOCALIZE.translation.DATEPICKER);
	this.calendarImg.setAttribute("style","position:relative; cursor:pointer;");
	
	//create div to hold calendar
	this.calendarDiv = document.createElement('DIV');
	this.calendarDiv.setAttribute("id","calendarContainer_" + this.id);
	this.calendarDiv.setAttribute("style","display:none; position:absolute; z-index : 100;");
	// add image and div
  	this.calendarA.appendChild(this.calendarImg);
  	
	this.node.appendChild(this.calendarA);
	this.node.appendChild(this.calendarDiv);
	
	// do not use setAttribute, ie does not allow placing class or style attributes with setAttribute.
	YAHOO.util.Dom.setStyle(this.calendarDiv, 'display', 'none');
	YAHOO.util.Dom.setStyle(this.calendarDiv, 'position', 'absolute');
	YAHOO.util.Dom.setStyle(this.calendarDiv, 'z-index', 100);
}
/**
 * this will only run when another controller subscribe to IAJS.OBSERVER is clicked
 * @private
 */
IAJS.CONTROLLER.DatePicker.prototype.onShowEvent = function(type, panel) {
    // hide calendar
   	if(this.visible) this.hide();
}
/**
 * @private
 */
IAJS.CONTROLLER.DatePicker.prototype.doNothing = function(e) {
	 // just to make sure that we never trigger the default event
    // this is necessarry because we remove the show handler on show (we add it back on hide)
    YAHOO.util.Event.stopEvent(e);
}
/**
 * @private
 * @param {String} initalDate optional value to set the calendar to (recommended the selected date is not the current date)
 **/
IAJS.CONTROLLER.DatePicker.prototype.create = function(ownerDate) {
	
	var config = {
		SHOW_WEEK_HEADER: true,
	    SHOW_WEEK_FOOTER: false,
	    SHOW_WEEKDAYS: true,
	    START_WEEKDAY: 1,
	    draggable:true,  
	    close:true
	};
	
	this.calendar = new YAHOO.widget.Calendar("calendar_" + this.id,  this.calendarDiv.getAttribute('id'), config);

	if(this.owner.elattr.mindate) {
		var minDate = new IAJS.Date(this.owner.elattr.mindate).init();
		this.calendar.cfg.setProperty("mindate",minDate.getDateObject());
	}
	if(this.owner.elattr.maxdate) {
    	var maxDate = new IAJS.Date(this.owner.elattr.maxdate).init();
		this.calendar.cfg.setProperty("maxdate",maxDate.getDateObject());
	}
	var pagedate = false;
	if(this.owner.date.isDate()) {
		this.calendar.cfg.setProperty("pagedate",this.owner.date.getMonth() + "/" +  this.owner.date.getYear());
		this.calendar.cfg.setProperty("selected",this.owner.date.asFormattedString(IAJS.CONFIG.dateFormat.american,"/"),false);
	}

	//set handler for select event
	this.calendar.selectEvent.subscribe(this.selectEventHandler, this, true);
	//display month and year in title bar								  
	this.calendar.changePageEvent.subscribe(function(e){this.cfg.setProperty('title',this.buildMonthLabel());}, this.calendar, true);
	this.calendar.changePageEvent.fire();
	//
	// this.calendar.render();
}
/**
 * @private
 */
IAJS.CONTROLLER.DatePicker.prototype.selectEventHandler = function(type, args, obj) {
	var dates = args[0];
	var date = dates[0];
	this.owner.setDate(date[2] + "-" + date[1] + "-" + date[0]);
	//only set owner date it is different from lastDate ()
 	this.hide();
	this.events.fire('onChange');
}
/**
 * Display the date picker
 */
IAJS.CONTROLLER.DatePicker.prototype.show = function(e) {
	// FIXME add tooltip to close icon (conform to despat)
	// FIXME calendar positioning
	if(!this.enabled) return false;
	
	this.create();	// create panel
	// tell the world that we are going to show ourselves, so that they can hide themselves
	this.world.fire(this.calendar);
	try {				
		// display calendar 
		this.calendar.show();
		//this.calendar.cfg.setProperty('context', [this.id,'tl','br']);
		this.visible = true;
	} catch(e){
		this.visible = false;
	} finally {
		// add hide handlers
		//YAHOO.util.Event.on(document, "keyup", this.hide, this, true); // to handle escape key
		YAHOO.util.Event.on(document, "click", this.hide, this, true); // to handle "click away"
	    // remove show handlers
		YAHOO.util.Event.removeListener(this.calendarA.getAttribute('id'), "click", this.show);
		// stop default event
		YAHOO.util.Event.stopEvent(e);
	}
}
/**
 * Hide the date picker
 */
IAJS.CONTROLLER.DatePicker.prototype.hide = function(e) {
	// if hide is called from onShowEvent there will be no 'e'
	if (e) {
		// check if clicked element was ancestor, allowing year(select) and month(text) to be selected
		var elt = YAHOO.util.Event.getTarget(e);
		var isAncestor = YAHOO.util.Dom.isAncestor(this.calendarDiv, elt);
		if(isAncestor){return}

		// hide if escape if in acompaning 'esc' is pressed 
		if (e.type == "keyup" &&  YAHOO.util.Event.getCharCode(e) != 27) return false;	
	}
	// hide the panel
	this.calendar.hide();
	this.visible = false;
	delete this.calendar;
    // add show handlers
	YAHOO.util.Event.on(this.calendarA.getAttribute('id'), "click", this.show, this, true);
	// remove hide handlers
	YAHOO.util.Event.removeListener(document, "keyup", this.hide);
	YAHOO.util.Event.removeListener(document, "click", this.hide);
	this.owner.focus();
}

/**
 * @private
 */
IAJS.CONTROLLER.DatePicker.prototype.now = function(){
	// TODO: add this to the date prototype
	var currentTime = new Date();
	return new Array(currentTime.getDate(), currentTime.getMonth() + 1, currentTime.getFullYear());
}
/**
 * @private
 * @return {integer} 1 date1 is bigger, -1 date2 is bigger, dates are equal 
 */
IAJS.CONTROLLER.DatePicker.prototype.compare = function(date1, date2){
	// TODO: add this to the date prototype
  	// TODO: return readable values
	if (date1[2] > date2[2]) return 1;
	else if (date1[2] < date2[2]) return -1;
	else if (date1[1] > date2[1]) return 1;
	else if (date1[1] < date2[1]) return -1;
	else if (date1[0] > date1[0]) return 1;
	else if (date1[0] < date1[0]) return -1;
	else return 0;
}
/**
 * Set enabled state of HTMLelements contained within the controller
 * @param {Boolean} value  The enabled state value 
 */
IAJS.CONTROLLER.DatePicker.prototype.setEnabled = function(value){
	this.enabled = value;
	this.events.fire("onEnableChange");
}
/**
 * @fileoverview The DefinitionLink Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.DefinitionListBase
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.DefinitionLink = function(node) {
  	IAJS.CONTROLLER.DefinitionLink.superclass.constructor.call(this,node);
	this.node = node;
	this.objectType = "DefinitionLink";
	this.css = {controls: 'controls', definitionList : 'defList'};
  	this.speechBubble;
}

YAHOO.extend(IAJS.CONTROLLER.DefinitionLink, IAJS.CONTROLLER.DefinitionListBase);
/**
 * Initialization of the controller
 */
 IAJS.CONTROLLER.DefinitionLink.prototype.init = function() {
 	//
	IAJS.CONTROLLER.DefinitionLink.superclass.init.call(this, this.css['definitionList'], "di_");
	if (this.deftextnode) {	
		// create bubble
		var div1 = document.createElement("div");
		YAHOO.util.Dom.addClass(div1,"definitionBox");
		YAHOO.util.Dom.setStyle(div1,"visibility","hidden");
		var div2 = document.createElement("div");
		YAHOO.util.Dom.addClass(div2,"speechBubble");
		YAHOO.util.Dom.addClass(div2,"tl");

		div1.appendChild(div2);
		for(var k=0; k < this.deftextnode.childNodes.length; k++) {
		  	div1.appendChild(this.deftextnode.childNodes[k].cloneNode(true));
		}
		document.body.appendChild(div1);
		this.floater = div1;
		this.speechBubble = div2;
	}
}
/**
 * The definition link will be displayed top left
 */
IAJS.CONTROLLER.DefinitionLink.prototype.hookOnTopLeft = function() {
	YAHOO.util.Dom.removeClass(this.speechBubble,"tr");
	YAHOO.util.Dom.removeClass(this.speechBubble,"bl");
	YAHOO.util.Dom.addClass(this.speechBubble,"tl");
}  
/**
 * The definition link will be displayed top right
 */
IAJS.CONTROLLER.DefinitionLink.prototype.hookOnTopRight = function() {
	YAHOO.util.Dom.removeClass(this.speechBubble,"tl");
	YAHOO.util.Dom.removeClass(this.speechBubble,"bl");
	YAHOO.util.Dom.addClass(this.speechBubble,"tr");
}
/**
 * The definition link will be displayed bottom right
 */
IAJS.CONTROLLER.DefinitionLink.prototype.hookOnBottomRight= function() {
	YAHOO.util.Dom.removeClass(this.speechBubble,"tl");
	YAHOO.util.Dom.removeClass(this.speechBubble,"bl");
	YAHOO.util.Dom.addClass(this.speechBubble,"br");
}
/**
 * The definition link will be displayed bottom left
 */
IAJS.CONTROLLER.DefinitionLink.prototype.hookOnBottomLeft= function() {
	YAHOO.util.Dom.removeClass(this.speechBubble,"tl");
	YAHOO.util.Dom.removeClass(this.speechBubble,"br");
	YAHOO.util.Dom.addClass(this.speechBubble,"bl");
}
/**
 * @fileoverview The Dropdownlist Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 * 
 */
IAJS.CONTROLLER.Dropdownlist = function(node) {
	this.node = node;
	this.objectType = "Dropdownlist";
	this.id;
	this.dropdown;
	this.rows;
	this.css = {controls: 'controls'};
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Dropdownlist
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Dropdownlist
	 */	
	this.events.add("onEnableChange");	
};

YAHOO.extend(IAJS.CONTROLLER.Dropdownlist, IAJS.CONTROLLER.BaseController);

/**
 * Initialization of the controller
 * @return {Boolean} True if initialization was successful otherwise false
 */
IAJS.CONTROLLER.Dropdownlist.prototype.init = function() {
	this.initAttribute();
	
	var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
	this.dropdown = YAHOO.util.Dom.getElementsBy(function(){return true;}, "select", controls)[0];
	YAHOO.util.Event.on(this.dropdown.id, "change", this.select, this, true);
};
IAJS.CONTROLLER.Dropdownlist.prototype.hookAfterInit = function() {return false};
IAJS.CONTROLLER.Dropdownlist.prototype.hookBeforeSubmit = function() {
	return false;
};
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Dropdownlist.prototype.validate = function() {
	//this.responseAction();
};
/**
 * 
 */
IAJS.CONTROLLER.Dropdownlist.prototype.getSelected = function() {
	var selected = {};
	var rows = YAHOO.util.Dom.getElementsBy(function(){return true;}, "option", this.node);
	for(var i=0; i<rows.length; i++) {
		selected[rows[i].value] = rows[i].selected;
	}
	return selected;
}
/**
 * onclick event from subscribed checkbox
 */	
IAJS.CONTROLLER.Dropdownlist.prototype.select = function(e,obj) {
	this.events.fire('onChange');
}

IAJS.CONTROLLER.Dropdownlist.prototype.setEnabledChanged = function() {
	this.events.fire('onEnableChange');
}

/**
 * @fileoverview The Email Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Email = function(node) {
	IAJS.CONTROLLER.Email.superclass.constructor.call(this, node);
	this.node = node;
	this.objectType = "Email";
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Simple(this);
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Email
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Email
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Email
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Email
	 */	
	this.events.add("validate");
};

YAHOO.extend(IAJS.CONTROLLER.Email, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Email.prototype.init = function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
		this.initAttribute(); 
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
};
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Email.prototype.validate = function() {
	var v = this.validationCode;
	this.validationCode = IAJS.VALIDATION.email(this.input.value);
	this.events.fire('validate');
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;		
};
/**
 * Set response based on validation code
 */	
IAJS.CONTROLLER.Email.prototype.responseAction = function() {
	switch(this.validationCode) {
		case IAJS.RESPONSE.OK:
			this.responseItem.clear();
			break;
		case IAJS.RESPONSE.INVALID:
			this.responseItem.error(LOCALIZE.messages.EMAIL_INVALID);
			break;
		case IAJS.RESPONSE.MANDATORY:
			this.responseItem.error(LOCALIZE.messages.EMAIL_MANDATORY);
			break;
		case IAJS.RESPONSE.FALLTHROUGH:
		default:
			this.responseItem.clear();
	}
};
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Email.prototype.getCheckInsideForm = function(){return true;}/**
 * @fileoverview The ExpandCollapseBox Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.ExpandCollapseBox = function(node) {
	this.node = node;
	this.classNode;			// HTMLelement that will recieve css classes to collapse en expand box
	this.box;
	this.boxHeight;
	this.control;			// HTMLelement that has event for opening and closing the box
	this.animate;
	this.objectType = "ExpandCollapseBox";
	this.css = {
		expand : "open",
		collapse : "closed"
	};
}

YAHOO.extend(IAJS.CONTROLLER.ExpandCollapseBox, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.init = function() {
	if (this.node) {
		// find nodes (input, response)
	  	this.box = YAHOO.util.Dom.getElementsByClassName("box","div",this.node)[0];
	  	this.classNode = this.node.getElementsByTagName("div")[0];
	  	// default to closed box
	  	this.collapse();
	  	var head = YAHOO.util.Dom.getElementsByClassName("head","div",this.node)[0];
		this.control = head.getElementsByTagName("span")[0];
	  	var region =  YAHOO.util.Dom.getRegion(this.box);
	  	this.boxHeight= region.bottom - region.top;
	  	/**
	  	 * animation init, if needed
	  	 */
		this.animate = (IAJS.CONFIG.animateCE === true) ? true : false;
		if (this.box && this.control) {
			if (this.animate && YAHOO.util.Anim) {
				//	
				this.speed = (YAHOO.lang.isNumber(IAJS.CONFIG.animateCESpeed)) ? IAJS.CONFIG.animateCESpeed : 0.2;
				this.hasAnimation = true;
				// check elattr:ease
				// if(typeof this.elattr == "undefined"){this.elattr = {} };
				/*try {
					//this.elattr.easing = (this.elattr && this.elattr.easing && YAHOO.lang.isFunction(YAHOO.util.Easing[this.elattr.easing] ) ) ? this.elattr.easing : null ;	
				} catch (e) {
					console.log(e);
				}
				//prepare animation
				this.animExpand = new YAHOO.util.Anim(this.box, null,this.speed, this.elattr.easing);
				this.animCollapse = new YAHOO.util.Anim(this.box, null,this.speed, this.elattr.easing);
				*/
				this.animExpand = new YAHOO.util.Anim(this.box, null,this.speed);
				this.animCollapse = new YAHOO.util.Anim(this.box, null,this.speed);
				//handle event on completed animation
				this.animExpand.onStart.subscribe(this.prepareAnim, this, true);
				this.animExpand.onComplete.subscribe(this.toggleCollapse, this, true);
				this.animCollapse.onComplete.subscribe(this.toggleCollapse, this, true);
				//handle contol click event
				YAHOO.util.Event.addListener(this.control, "click", this.toggleCollapseAnim, this, true);
			} else {
				//handle contol click event
				YAHOO.util.Event.addListener(this.control, "click", this.toggleCollapse, this, true);
			}			
		}
	}
}
/**
 * Open the box
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.expand = function(){
	(YAHOO.util.Dom.hasClass(this.classNode,this.css.collapse)) ? 
			YAHOO.util.Dom.replaceClass(this.classNode, this.css.collapse, this.css.expand) :  
			YAHOO.util.Dom.addClass(this.classNode,this.css.expand) ;
}
/**
 * 
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.collapse = function(){	
	(YAHOO.util.Dom.hasClass(this.classNode,this.css.expand)) ?
		YAHOO.util.Dom.replaceClass(this.classNode,this.css.expand,this.css.collapse) : 
		YAHOO.util.Dom.addClass(this.classNode,this.css.collapse) ;
	
}
/**
 * Change collapse state of the box with animation
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.toggleCollapseAnim = function() {
	
	if(this.isCollapsed()) {
		this.calculateHeight();
		YAHOO.util.Dom.setStyle(this.box, "height", 0); // this must be 0 don't use this.boxHeight, else there is a 'blink' the first time opening the box
		YAHOO.util.Dom.setStyle(this.box, "visibility", "visible");
		YAHOO.util.Dom.setStyle(this.box, "display", "block");
		this.animExpand.attributes.height = {from: 0, to: this.boxHeight, unit: 'px'};
    	this.animExpand.animate();
	}
	else {
		this.animCollapse.attributes.height = {from: this.boxHeight, to: 0, unit: 'px'};
    	this.animCollapse.animate();
	}
}

/**
 * Change collapse state of the box with animation
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.prepareAnim = function() {
	YAHOO.util.Dom.setStyle(this.box, "height", 0); // this must be 0 don't use this.boxHeight, else there is a 'blink' the first time opening the box
	 YAHOO.util.Dom.setStyle(this.box, "visibility", "visible");
	 YAHOO.util.Dom.setStyle(this.box, "display", "block");
}

/**
 * Change collapse state of the box, if animation is enabled this will also run at end of the animation cycle
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.toggleCollapse = function() {
	if(this.isCollapsed()) {
		this.expand();
	} else {
		this.collapse();
		if(this.hasAnimation) {
			YAHOO.util.Dom.setStyle(this.box, "visibility", "hidden");
			YAHOO.util.Dom.setStyle(this.box, "display", "none");
		}
	}
}
/**
 * Provide collapsed state information
 * @return {boolean} indication if controller is in collapsed state
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.isCollapsed = function(){
	// if not expaned we must be collapsed
	return YAHOO.util.Dom.hasClass(this.classNode,this.css.collapse);
}

/**
 * Provide box height information on an element with display none.
 * @return {void} sets object boxHeight property
 */
IAJS.CONTROLLER.ExpandCollapseBox.prototype.calculateHeight = function() {
	if(!this.boxHeight || this.boxHeight == "NaN" ) {
		// somehow we need to calculate the height on an element with display none
		YAHOO.util.Dom.setStyle(this.box, "top", "-999em");
		YAHOO.util.Dom.setStyle(this.box, "left", "-999em");
		YAHOO.util.Dom.setStyle(this.box, "display", "block");
		
		
		region =  YAHOO.util.Dom.getRegion(this.box);
		this.boxHeight = region.bottom - region.top;
		//this.boxHeight = this.node.innerHeight;
		
		this.height = (this.box.scrollHeight > this.box.offsetHeight) ? this.box.scrollHeight : this.box.offsetHeight; // browser specific
		
		//this.height = this.box.scrollHeight;
		//this.p = YAHOO.util.Dom.getX(this.box);
		this.p = this.node.scrollHeight;
		this.p2 = this.node.scrollTop;
		
		YAHOO.util.Dom.setStyle(this.box, "top", "auto"); //need auto instead of 0 when expand-collapse is expanded by default
		YAHOO.util.Dom.setStyle(this.box, "left", "auto");//need auto instead of 0 when expand-collapse is expanded by default
		YAHOO.util.Dom.setStyle(this.box, "display", "none");
	} else {
		this.p = this.node.scrollHeight;
		this.p2 = this.node.scrollTop;
	}
}

/**
 * @fileoverview The FieldLevelHelpController
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */

/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.FieldLevelHelp = function(node) {
	this.node = node;
	this.cNode;
	this.deflistName;
	this.deftextnode;
	this.deflink;
	this.panel;
	this.visible = false;
	this.objectType = "FieldLevelHelp";
	this.css = {controls: 'controls', fieldHelpList : 'defList help'};
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the controller is shown.
	 * @name show
	 * @memberOf IAJS.CONTROLLER.FieldLevelHelp
	 */	
	this.events.add("show");
	/**
	 * Fires after the controller is hidden.
	 * @name hide
	 * @memberOf IAJS.CONTROLLER.FieldLevelHelp
	 */	
	this.events.add("hide");
};

YAHOO.extend(IAJS.CONTROLLER.FieldLevelHelp,IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.init = function() {
	//
	if (this.node) {
		this.id = this.node.id;
		//get elattributes
		this.initAttribute();
		// hide definition lists
		this.deflists = YAHOO.util.Dom.getElementsByClassName(this.css['fieldHelpList'],"div")[0];
		YAHOO.util.Dom.addClass(this.deflists, "hidden");
		// extract our definition
		var defid = this.node.getAttribute('href');
		defid = defid.substring(defid.lastIndexOf("#") + 1); // FF = "#the_href_value", IE = "fullURL/#the_href_value"
		//
		this.deflink = document.getElementById(defid);		
		if (this.deflink) {
		  	this.deftextnode = null;
		  	var name = "#" + this.node.id;
			var elm = YAHOO.util.Dom.getElementsBy(function(){return true}, 'dd', this.deflink.parentNode);
			for(var i=0, l = elm.length; i < l; i++){
				var backlinks = YAHOO.util.Dom.getElementsBy(function(el) { return el.href.indexOf(name) > -1;},"a",elm[i]);
				
				if(backlinks.length > 0){
					this.deftextnode = elm[i];
					YAHOO.util.Dom.batch(backlinks, function(el){YAHOO.util.Dom.setStyle(el,"display","none");});
					i = l; // found what we were looking for, leave for loop
		  		} 
		  	}
			// add click event to term
			YAHOO.util.Event.on(this.node, "click", this.show, this, true);
			YAHOO.util.Event.on(this.node, "click", this.doNothing, this, true);
				
			// listen for show event in our world
			this.fldWorld = IAJS.OBSERVER.getInstance();
			this.fldWorld.subscribe(this.onShowEvent, this, true);	
		}
	}
};

/**
 * Create help container
 * @private
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.create = function() {
	// override css class names if provided
	this.panel = new YAHOO.widget.Panel("panel_" + this.id, { width:"10em", visible:false, draggable:false, close:false, constraintoviewport:true} );
  	//myPanel = new YAHOO.widget.Panel("win", {width:"10em",visible: false,constraintoviewport: true,underlay:"shadow",close:false,draggable:false} );
	this.panel.setHeader(this.deflink.innerHTML);
	this.panel.setBody(this.deftextnode.innerHTML);
	//this.panel.cfg.setProperty('constraintoviewport',true);
	this.panel.cfg.setProperty('context', [this.id,'tr']);
	//this.panel.cfg.setProperty('iframe', false);
	this.panel.render(document.body); 
	//
	this.panel.show();	
};
/**
 * Called when another controller subscribed to IAJS.OBSERVER is clicked
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.onShowEvent = function(type, panel) {
    // check if our floater is visible, if it is then we hide ourselves
    if(this.visible) this.hide();
}
/**
 * Make sure that we never trigger the default event
 * @private
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.doNothing = function(e) {
	 // just to make sure that we never trigger the default event
    // this is necessarry because we remove the show handler on show (we add it back on hide)
    YAHOO.util.Event.stopEvent(e);
};
/**
 * Hide the panel under these conditions:
 * 	   - the escape key is pressed in the field fieldlevelhelp belongs to
 *	   - a click anywhere on the screen
 *	   - onblur when not blurring to the related input field
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.hide = function(e){
	// if hide is called from onShowEvent there will be no 'e'
	if (e) {
		var elt = YAHOO.util.Event.getTarget(e);
		
		// do not hide if target is field that fieldlevelhelp belongs to
		if(("help_" + elt.getAttribute('id')) === this.controllerId) return false;
		// do not hide if target is fieldlevelhelp
		if (e.type == "click" && elt.tagName !== 'HTML'  && elt.parentNode.getAttribute('id') == "panel_" + this.id) return false;
		// hide if 'esc' or tab is pressed 
		if (e.type == "keyup") {
			charCode = YAHOO.util.Event.getCharCode(e);
			hide = false;
			if(charCode == 27 || charCode == 9) hide = true;
			if(!hide) return false;
		}
	}
	
	// hide the panel
	this.panel.hide();
	this.visible = false;	
	
    // add show handlers
	YAHOO.util.Event.on(this.node, "click", this.show, this, true);

	// remove hide handlers
	YAHOO.util.Event.removeListener(document, "keyup", this.hide);
	YAHOO.util.Event.removeListener(document, "click", this.hide);
	
	// trigger custom controller event
	this.events.fire("hide");	
};
/**
 * Show the panel under these conditions:
 * 	- click event on this.node
 */
IAJS.CONTROLLER.FieldLevelHelp.prototype.show = function(e){
	// create panel on first time use
	if(!this.panel)	this.create(); 
	
	// tell the world that we are going to show ourselves, so that they can hide themselves
	this.fldWorld.fire(this.panel);
	
	// position ourself
	this.panel.cfg.setProperty('context', [this.id,'tl','br']);
	
	// make ourselves visibility
	this.panel.show();
	this.visible = true;
	
	// add hide handlers
	YAHOO.util.Event.on(document, "keyup", this.hide, this, true); // to handle escape key
	YAHOO.util.Event.on(document, "click", this.hide, this, true); // to handle "click away"
    
    // remove show handlers
	YAHOO.util.Event.removeListener(this.id, "click", this.show);
	
	// stop default event
	YAHOO.util.Event.stopEvent(e);
	
	// trigger custom controller event
	this.events.fire("show");	
};
/**
 * @fileoverview The Form Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 * 
 * @title Form
 * @namespace IAJS.CONTROLLER 
 * @description <p>
 * 
 * </p>
 *  
 */
 
/**
 * @constructor
 * @param form {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-40002357">HTMLFormElement</a>} form The form to create the controller for.
 */
IAJS.CONTROLLER.Form = function(form){
	this.form = form;
	/**
	 * @type {Object} reference to IAJS.CONTROLLER controllers located within the form
	 */
	this.controllers = {};
	/**
	 * @type {Object} Custom controller events
	 */
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @event onSubmit Triggert after <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-40002357">HTMLFormElement</a> onsubmit event is triggert
	 * @memberOf IAJS.CONTROLLER.Form
	 */	
	this.events.add("onSubmit");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @event onSubmitError Triggert after IAJS.CONTROLLER.Form onSubmit event has compleeted with a false value form an event subscriber.
	 * @memberOf IAJS.CONTROLLER.Form
	 */	
	this.events.add("onSubmitError");
	
}
/**
 * 
 */
IAJS.CONTROLLER.Form.prototype.init = function(){
	//fire custom onSubmit event when form submit event is triggert
	YAHOO.util.Event.on(this.form, "submit", this._handleSubmit, this, true);
	//stop default event 
	//YAHOO.util.Event.on(this.form, "submit", function(e){YAHOO.util.Event.stopEvent(e);}, this, true);
	//return this to allow init for shorter new call 
	return this;	
}
/**
 * Register controller to subscribe to specific IAJS.CONTROLLER.Form events
 * @see
 * @param {IAJS.CONTROLLER} c The controller to register
 */
 IAJS.CONTROLLER.Form.prototype.register = function(c){
 	if(c && c.controllerId){
		this.controllers[c.controllerId] = c;			
		//hook into IAJS.formCollection custom event
		this.events.subscribe(c.hookBeforeSubmit, c, true);
	}
 }
/**
 * @private
 */
 IAJS.CONTROLLER.Form.prototype._handleSubmit = function(e){
	var value = this.events.fire("onSubmit");
	if (!value){
		//stop default event 
		YAHOO.util.Event.stopEvent(e);	 	
	}
 } 
/**
 * @private
 */
 IAJS.CONTROLLER.Form.prototype._handleSubmitError = function(e){
 	var t = YAHOO.util.Event.getTarget(e).id;
 	var value = IAJS.formCollection[t].events.fire('onSubmit');
 } /**
 * The Number Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Number = function(node) {
	this.node = node;
	this.objectType = "Number";
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Simple(this);	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Number
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Number
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Number
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Number
	 */	
	this.events.add("validate");
}

YAHOO.extend(IAJS.CONTROLLER.Number, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Number.prototype.init = function() {	
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
				
		/*this.input = YAHOO.util.Dom.getElementsByClassName("textfield","input",this.node)[0];*/
		this.initAttribute();
		this.response = this.getResponse(this.input.id);
	}
	if (this.hasResponse()) {
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Number.prototype.hookAfterInit =  function() {
	this.validate();
}
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.Number.prototype.validate = function() {
	var v = this.validationCode;
	this.validationCode = IAJS.VALIDATION.number(this.input.value,this.elattr['min'],this.elattr['max'],this.elattr['decimals']);
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;	
}
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.Number.prototype.responseAction = function() {
	switch(this.validationCode) {
		case IAJS.RESPONSE.OK:
			this.responseItem.clear();
			break;
		case IAJS.RESPONSE.INVALID: 
			this.responseItem.error(LOCALIZE.messages.NUMBER_INVALID);
			break;
    	case IAJS.RESPONSE.TOLOW:
    		this.responseItem.error(LOCALIZE.messages.NUMBER_TOO_LOW);
			break;
    	case IAJS.RESPONSE.TOHIGH:
    		this.responseItem.error(LOCALIZE.messages.NUMBER_TOO_HIGH);
			break;
   	 	case IAJS.RESPONSE.NUMBER.EXCEED_DECIMAL:
   	 		this.responseItem.error(LOCALIZE.messages.NUMBER_EXCEED_DECIMAL);
			break;
		case IAJS.RESPONSE.NUMBER.NO_FLOAT:
			this.responseItem.error(LOCALIZE.messages.NUMBER_NO_FLOAT);
			break;
		case IAJS.RESPONSE.MANDATORY:
			this.responseItem.error(LOCALIZE.messages.NUMBER_MANDATORY);
			break;
		case IAJS.RESPONSE.FALLTHROUGH:
			this.responseItem.clear();
			break;
		default:
			this.responseItem.clear();
	}	
}
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Number.prototype.getCheckInsideForm = function(){return true;}
/**
 * The Radio Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Radio = function(node,owner) {
	this.node = node;
	this.owner = owner;
	this.isSelected = false;
	this.objectType = "Radio";
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Radio
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Radio
	 */	
	this.events.add("onEnableChange");
};

YAHOO.extend(IAJS.CONTROLLER.Radio, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Radio.prototype.init = function(){ 
	if (this.node) {
		this.id = this.node.getAttribute("id");
		YAHOO.util.Event.on(this.id, "click", this.owner.select, this, this.owner);
	}
	//
	return this;
};

IAJS.CONTROLLER.Radio.prototype.select = function() {
	if(this.isSelected !== this.node.checked){this.events.fire('onChange')}
	this.isSelected = this.node.checked;
	
}
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Radio.prototype.validate = function() {
	return false;
};
/**
 * Set response based on validation code
 */	
IAJS.CONTROLLER.Radio.prototype.responseAction = function() {
	return false;
};
/**
 * The Radiolist Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Radiolist = function(node) {
	this.node = node;
	this.objectType = "Radiolist";
	this.group = new Object;
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Radiolist
	 */	
	this.events.add("onChange");
};

YAHOO.extend(IAJS.CONTROLLER.Radiolist, IAJS.CONTROLLER.BaseController);

/**
 * Initialization of the controller
 * @return {Boolean} True if initialization was successful otherwise false
 */
IAJS.CONTROLLER.Radiolist.prototype.init = function() {
	this.initAttribute();
	var rows = YAHOO.util.Dom.getElementsBy(function(el){ return (el.getAttribute("type") == "radio")}, "input", this.node);
	for(var i=0, l = rows.length ;i<l;i++) {
		node = rows[i];
		nodeId = node.getAttribute("id");
		this.group[nodeId] = new IAJS.CONTROLLER.Radio(node,this).init();
	}
	this.select();
};

IAJS.CONTROLLER.Radiolist.prototype.hookAfterInit = function() {return false};
IAJS.CONTROLLER.Radiolist.prototype.hookBeforeSubmit = function() {
	return false;
};
/**
 * Validate the data belonging to this controller
 */	
IAJS.CONTROLLER.Radiolist.prototype.validate = function() {
};
/**
 * 
 */
IAJS.CONTROLLER.Radiolist.prototype.getSelected = function() {
	var selected = {};
	for(key in this.group) selected[key] = this.group[key].isSelected;
	return selected;
}
/**
 * onclick event from subscribed checkbox
 */	
IAJS.CONTROLLER.Radiolist.prototype.select = function(e,obj) {
	if(this.group){
		for(var i in this.group) {
			this.group[i].select();
		}
		this.events.fire('onChange');
	}
	  
}

IAJS.CONTROLLER.Radiolist.prototype.setEnabledChanged = function() {
	this.events.fire('onEnableChange');  
}



/**
 * The tabpane controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 * @requires IAJS.CONTROLLER.BaseController
 */ 
 /**
  * @constructor
  * @base IAJS.CONTROLLER.BaseController
  * @param {HTMLelement} node The eltype element to create the controller for
  */
IAJS.CONTROLLER.Tabpane = function(node) {
	this.node = node;
	this.tabView;
	this.objectType = "Tabpane";
	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Tabpane
	 */	
	this.events.add("onChange");
}
YAHOO.extend(IAJS.CONTROLLER.Tabpane, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Tabpane.prototype.init = function(){	
	if (this.node) {
		
		if (!this.controllerId){
			var v = IAJS.controllerManager.initControllerId(this); // if false then no controllerId was assignd to controller 
			if (v){
				//assign controllerId to node if the node has no id
				if(!this.node.id)this.node.setAttribute("id",this.controllerId);
				
				YAHOO.widget.TabView.prototype.CLASSNAME = "tabpane";
				YAHOO.widget.TabView.prototype.CONTENT_PARENT_CLASSNAME = 'content';
				YAHOO.widget.TabView.prototype.TAB_PARENT_CLASSNAME = 'nav';
				YAHOO.widget.Tab.prototype.LABEL_INNER_TAGNAME = 'span';
				YAHOO.widget.Tab.prototype.ACTIVE_CLASSNAME = 'active';
				
				this.tabView = new YAHOO.widget.TabView(this.controllerId);
				// propagate event from Yahoo widget to tabpane controller event
				this.tabView.subscribe("activeTabChange", IAJS.CONTROLLER.Tabpane.prototype._tabChangeHandler, this, true);
			}
		}
	}
}
/**
 * Handler for tab changes
 * @private
 */
IAJS.CONTROLLER.Tabpane.prototype._tabChangeHandler = function(eventInfo){
	/**
	 *  prevValue and newValue get passed by YAHOO.widget.TabView eventInfo
	 */
 	var oldIndex = this.tabView.getTabIndex(eventInfo.prevValue);
 	var newIndex = this.tabView.getTabIndex(eventInfo.newValue);
	this.events.fire('onChange', {oldIndex: oldIndex, newIndex: newIndex} );
}
/**
 * Label of the tab
 * @param {Number} index The index of the tab to get the label from
 */
IAJS.CONTROLLER.Tabpane.prototype.getLabel = function(index){
	var t = this.tabView.getTab(index);
	return (t) ? t._configs.label.value : false;
}
/**
 * 
 */
IAJS.CONTROLLER.Tabpane.prototype.getTabContentElement = function(index){
	var t = this.tabView.getTab(index);
	return (t) ? t._configs.contentEl.value : false;
}
/**
 * 
 */
IAJS.CONTROLLER.Tabpane.prototype.activeTabIndex = function(index){
	return this.tabView.get('activeIndex');
}
/**
 * 
 */
 /*
IAJS.CONTROLLER.Tabpane.prototype.asArray = function(index){
	return this.tabView.get('tabs');
}
*/
/**
 * The TelephoneExtended Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.TelephoneBase
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.TelephoneExtended = function(node) {
	this.node = node;
	this.countryElm;	// HTMLelement that hold country value
	this.objectType = "TelephoneExtended";
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Simple(this);	
}
YAHOO.extend(IAJS.CONTROLLER.TelephoneExtended, IAJS.CONTROLLER.TelephoneBase);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.TelephoneExtended.prototype.init= function() {
	if(this.node) {	
		IAJS.CONTROLLER.Vat.superclass.init.call(this, this.node);
		this.countryElm = YAHOO.util.Dom.getElementsBy(function(el){return true},"select",this.node)[0];
		YAHOO.util.Event.on(this.countryElm, "blur", this.validate, this, true);
	}
}
/**
 * return country property 
 */
IAJS.CONTROLLER.TelephoneExtended.prototype.getCountry = function() {
 	return (this.countryElm)? this.countryElm.options[this.countryElm.selectedIndex].value : null;
};/**
 * The TelephoneBase Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
 /**
 * @constructor
 * @base IAJS.CONTROLLER.TelephoneBase
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.TelephoneSimple = function(node) {
	this.node = node;
	this.objectType = "TelephoneSimple";
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Simple(this);	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.TelephoneSimple
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.TelephoneSimple
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.TelephoneSimple
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.TelephoneSimple
	 */	
	this.events.add("validate");
}

YAHOO.extend(IAJS.CONTROLLER.TelephoneSimple, IAJS.CONTROLLER.TelephoneBase);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.TelephoneSimple.prototype.init = function() {
	if(this.node) {
		IAJS.CONTROLLER.TelephoneSimple.superclass.init.call(this, this.node);
	}
}
/**
 * return country property 
 */
IAJS.CONTROLLER.TelephoneSimple.prototype.getCountry = function() {
	return "BE"; 
};
/**
 * The TextareaController
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Textarea = function(node) {
	this.node = node;
	this.rows;
	this.x = 0;
	this.y = 0;
	this.maxExpand;
	this.maxLength = 0;
	this.remaining;		// if a maxLength is given, contains the number of characters remaining
	
	this.objectType = "Textarea";
	
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Simple(this);
	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Textarea
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Textarea
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Textarea
	 */	
	this.events.add("validate");	
}

YAHOO.extend(IAJS.CONTROLLER.Textarea, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Textarea.prototype.init = function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("textarea", controls)[0];	
		this.initAttribute(); 	
		if(this.input) this.rows = (this.input.getAttribute("rows")) ? this.input.getAttribute("rows") : 5;
    	this.setExpand();
		this.maxLength = this.elattr["maxlength"];
		this.resizer = YAHOO.util.Dom.getElementsByClassName("boxSizer","div",this.node)[0];
		this.spanResizer = YAHOO.util.Dom.getElementsByClassName("spanResizer","span",this.node)[0];
		YAHOO.util.Event.on(this.input, "keyup", this.keyup, this, true);
		YAHOO.util.Event.on(this.input, "change", this.keyup, this, true);
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
		//YAHOO.util.Event.on(this.input, "click", this.mousedown, this, true);
	}
}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Textarea.prototype.hookAfterInit = function() {
    this.validate();
    this.updateRows();
}
/**
 * Called by a keyup event, can cause the textarea to change size and update the characters left counter  
 */
IAJS.CONTROLLER.Textarea.prototype.keyup = function(e) {
	this.responseAction();
	this.updateRows();
}
/**
 * Check if textarea is allowed to expand, set maxexpand or false
 * @private
 */
IAJS.CONTROLLER.Textarea.prototype.setExpand = function() {
	doExpand = IAJS.CONFIG.expandTextarea;
	attr = this.elattr['maxexpand']*1;
	if(IAJS.CONFIG.expandTextarea === false || attr===false){
		this.maxExpand = false;
	} else {
		this.maxExpand = (attr > this.rows) ? attr : this.rows * 2; // calc maximum default number of rows that will grow the textarea
	}
}
/**
 * Increase the number of rows for the textarea if needed
 * the area will resize if 
 * 		- the number or characters is smaller than the maximum allowed
 * 		- the current number of rows is smaller then the maximum allowed
 * @private
 */
IAJS.CONTROLLER.Textarea.prototype.updateRows = function() {
	if(this.maxExpand) {
		var number_of_enters = this.input.value.split("\n").length;
		var number_of_lines = parseInt(this.input.value.length / this.input.getAttribute("cols"));
		var number_rows = (number_of_enters >= number_of_lines)? number_of_enters : number_of_lines;
		if(number_rows <= this.rows){
			this.input.rows = this.rows;
		} else if (number_rows <= this.maxExpand) {
			YAHOO.util.Dom.setStyle(this.input,"height","");
			this.input.rows = number_rows;
		}
	}
}
/**
 * Called by the mousedown event
 */
IAJS.CONTROLLER.Textarea.prototype.mousedown = function(e) {
	YAHOO.util.Dom.setStyle(this.input,"color","#ff0000");
	var reg  = new YAHOO.util.Dom.getRegion(this.input);
	YAHOO.util.Event.on(this.input, "mousemove", this.mousemove, this, true);
	YAHOO.util.Event.on(this.input, "mouseup", this.mouseup, this, true);
}
/**
 * Called by the mouseup event
 */
IAJS.CONTROLLER.Textarea.prototype.mouseup = function() {
	YAHOO.util.Dom.setStyle(this.input,"color","#000000");
	//YAHOO.util.Dom.setStyle(this.input,"display","inline");	
	//YAHOO.util.Dom.setStyle(this.spanResizer,"display","none");
	YAHOO.util.Event.removeListener(this.input, "mousemove", this.mousemove);
}
/**
 * Called by the mousemove event
 */
IAJS.CONTROLLER.Textarea.prototype.mousemove = function(e) {
	YAHOO.util.Dom.setStyle(this.input,"color","#00ff00");
	/*
	var xy = YAHOO.util.Event.getXY(e);
	YAHOO.util.Dom.setStyle(this.spanResizer,'width',parseInt(xy[0]));
	YAHOO.util.Dom.setStyle(this.spanResizer,'height',parseInt(xy[1]));
	*/
}
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.Textarea.prototype.validate = function() {
	var v = this.validationCode;
	this.events.fire('validate');
	this.validationCode = IAJS.VALIDATION.textarea(this.input.value,this.elattr.maxlength);
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');	
}
/**
 * Calculate the remaining number of allowed characters for the textarea
 * @private
 */
IAJS.CONTROLLER.Textarea.prototype.getRemaining = function() {
	return (this.maxLength > 0) ?	LOCALIZE.translation.REMAINING + " " + (this.maxLength - this.input.value.length)	: "";
}
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.Textarea.prototype.responseAction = function() {
	var msg = this.getRemaining();
	
	switch(this.validationCode) {
		case IAJS.RESPONSE.OK:
	  		this.responseItem.confirmation(msg);
	  		break;		
	  	case IAJS.RESPONSE.INVALID:
	  		if(msg.length > 0){msg += ", "};	
	  		this.responseItem.error(LOCALIZE.messages.TEXT_MANDATORY + msg);
			break;
	  	case IAJS.RESPONSE.TEXT.TOLONG :
	  		if(msg.length > 0){msg += ", "};	
	  		this.responseItem.error(LOCALIZE.messages.TEXT_TOLONG + msg);
	  		break;
	  	case IAJS.RESPONSE.FALLTHROUGH:
	  	default:
	  		this.responseItem.confirmation(msg);
	}
}
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Textarea.prototype.getCheckInsideForm = function(){return true;}/**
 * Textfield controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
 /**
  * @constructor
  * @base IAJS.CONTROLLER.BaseController
  * @param {HTMLelement} node The eltype element to create the controller for
  */
IAJS.CONTROLLER.Textfield = function(node){
	this.node = node;
	this.objectType = "Textfield";
	this.css = {controls: 'controls'};	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Textfield
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Textfield
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Textfield
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Textfield
	 */	
	this.events.add("validate");
}

YAHOO.extend(IAJS.CONTROLLER.Textfield, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Textfield.prototype.init = function(){
	if(this.node) {		
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
		this.initAttribute();		
	}
};
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Textfield.prototype.hookAfterInit =  function(){
	
};
/**
 * Set enabled state of HTMLelements contained within the controller
 * @param {Boolean} value  The enabled state value
 * @param {Object} args	Used when function is called from custom event
 * @param {Object} me Execution scope when function is called from custom event 
 */
IAJS.CONTROLLER.Textfield.prototype.setEnabled = function(value){
	IAJS.CONTROLLER.Textfield.superclass.setEnabled.call(this, value);
};
/**
 * 
 */
 IAJS.CONTROLLER.Textfield.prototype.setVisible = function(value){
 	(value) ? this.input.removeAttribute("hidden") : this.input.setAttribute("hidden","hidden");
 };
/**
 * Handle onChange event from subordinate controller 
 */
IAJS.CONTROLLER.Textfield.prototype.onSubordinateChange = function() {
	var subordinate = IAJS.ELATTR.getSubordinate(this);
	if(subordinate){
		var selected = IAJS.controllerCollection[subordinate.controller].getSelected();
		if (selected) this.setEnabled(selected[subordinate.element]);
		//check if we need to hide the label once (special case if subordinate is dropdownlist
		if(!this.labelChecked && IAJS.controllerCollection[subordinate.controller].objectType == "Dropdownlist" ){
			var l =  YAHOO.util.Dom.getElementsBy(function(el){ return (el.getAttribute("for")); },"label",this.node)[0];
			YAHOO.util.Dom.addClass(l, "hidden");
		}
		this.labelChecked = true;
	}
	
};
/**
 * The Time Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for
 */
IAJS.CONTROLLER.Time = function(node) {
	IAJS.CONTROLLER.Time.superclass.constructor.call(this, node);
	this.objectType = "Time";
	this.node = node;
	this.id;
	this.responseItem = new IAJS.response.Item(this);
	this.css = {controls: 'controls'};
		
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Time
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Time
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Time
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Time
	 */	
	this.events.add("validate"); 
}

YAHOO.extend(IAJS.CONTROLLER.Time, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Time.prototype.init = function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];
		this.id = this.input.id;
		this.initAttribute(); 
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
}
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Time.prototype.hookAfterInit = function() {
    this.validate();
};
IAJS.CONTROLLER.Time.prototype.getTime = function() {
	return (this.input) ? this.input.value : false;
}
/**
 * Validate the data belonging to this controller
 */
IAJS.CONTROLLER.Time.prototype.validate = function() {
	var v = this.validationCode;
	//valide this time value
	this.validationCode = IAJS.VALIDATION.time(this.input.value,this.elattr['mintime'],this.elattr['maxtime']);
	//if this time is valid and we have a master, validate
	if ((m = IAJS.ELATTR.getMaster(this)) && (this.validationCode == IAJS.RESPONSE.OK)){
		var key = (m.controller) ? m.controller : m.element;
		var master = IAJS.controllerCollection[key];
		if(master && master.validationCode == IAJS.RESPONSE.OK) {
			this.validationCode = IAJS.VALIDATION.timeRange(this.getTime(), master.getTime(), this.elattr.mintimediff, this.elattr.maxtimediff);
		}		
	}
	//display response
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;
};
/**
 * 
 */
 
/**
 * Set response based on validation code
 */
IAJS.CONTROLLER.Time.prototype.responseAction = function() {
	switch(this.validationCode) {
	  case IAJS.RESPONSE.OK:
		var timeString, dateTime = this.input.value.toStructuredTime().toReadableTime(null);
		if (dateTime.getSeconds() == 0 && dateTime.getMinutes() == 0)
		  timeString = dateTime.format("%G% u");
		if (dateTime.getSeconds() == 0 && dateTime.getMinutes() != 0)
		  timeString = dateTime.format("%G% u %i%");
		if (!timeString)
		  timeString = dateTime.format("%G% u %i%, %S% sec");
		this.responseItem.confirmation(timeString);
		/*Response.set(this.response,"confirmation",timeString);*/
		break;
	  case IAJS.RESPONSE.INVALID:
		this.responseItem.error(LOCALIZE.messages.TIME_INVALID);
		/*Response.set(this.response,"error",LOCALIZE.messages.TIME_INVALID);*/
		break;
      case IAJS.RESPONSE.OUTOFRANGE:
        // FIXME: move formatting this to toReadableTime()
		var timeString, dateTime = this.input.value.toStructuredTime().toReadableTime(null);
		if (dateTime.getSeconds() == 0 && dateTime.getMinutes() == 0)
		  timeString = dateTime.format("%G% u");
		if (dateTime.getSeconds() == 0 && dateTime.getMinutes() != 0)
		  timeString = dateTime.format("%G% u %i%");
		if (!timeString)
		  timeString = dateTime.format("%G% u %i%, %S% sec");		
		this.responseItem.error(timeString + " " + LOCALIZE.messages.TIME_OUT_OF_RANGE);
		/*Response.set(this.response,"error", timeString + " " + LOCALIZE.messages.TIME_OUT_OF_RANGE);*/
        break;
	  case IAJS.RESPONSE.MANDATORY:
		this.responseItem.error(timeString + " " + LOCALIZE.messages.TIME_MANDATORY);
		/*Response.set(this.response,"error",LOCALIZE.messages.TIME_MANDATORY);*/
        break;
	  case IAJS.RESPONSE.FALLTHROUGH:
	  default:
		this.responseItem.clear();
		/*Response.clear(this.response);*/
	}
};
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Time.prototype.getCheckInsideForm = function(){return true;}
 /**
 * Handle onChange event from subordinate controller
 */
IAJS.CONTROLLER.Time.prototype.onSubordinateChange = function() {
	var subordinate = IAJS.ELATTR.getSubordinate(this);
	// if there is a elattr:subordinate and the value of the element part is the same, disable this controller
	if(subordinate)	me.setEnabled(args[0].value == subordinate.element);
}
/**
 * The Email Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for.
 */
IAJS.CONTROLLER.Transferlist = function(node) {
	this.node = node;
	this.containerLabel;
	this.objectType = "Transferlist";
	this.responseItem = new IAJS.response.Simple(this);
}

YAHOO.extend(IAJS.CONTROLLER.Transferlist, IAJS.CONTROLLER.BaseController);

IAJS.CONTROLLER.Transferlist.prototype.init = function() {
	if(this.node) {
	 	this.input = this.node.getElementsByTagName("select")[0];
		this.containerLabel = YAHOO.util.Dom.getElementsBy(function(el){ return (el.getAttribute("for")); },"label",this.node)[0];
		this.initAttribute();
		if(this.input) {
			this.createTransferList();
		}		
	}
}


IAJS.CONTROLLER.Transferlist.prototype.createTransferList =  function() {
	this.list = new IAJS.CONTROLLER.TransferlistObject(this);
	this.list.init();
}

IAJS.CONTROLLER.Transferlist.prototype.hookAfterInit =  function() {
	//this.validate();
}

IAJS.CONTROLLER.Transferlist.prototype.validate = function() {

}

IAJS.CONTROLLER.Transferlist.prototype.responseAction = function() {
	switch(this.validationCode) {
		case IAJS.RESPONSE.OK:
			this.responseItem.clear();
			break;
		case IAJS.RESPONSE.INVALID:
			this.responseItem.error(LOCALIZE.messages.TRANSFER_INVALID);
			break;
		case IAJS.RESPONSE.MANDATORY:
			this.responseItem.error(LOCALIZE.messages.TRANSFER_MANDATORY);
			break;
		case IAJS.RESPONSE.FALLTHROUGH:
			break;
		default:
			this.responseItem.clear();
	}
}


/**
 * TransferlistObjectController
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @param {IAJS.CONTROLLER.Transferlist} owner The Transferlist controller to create the controller for.
 */
IAJS.CONTROLLER.TransferlistObject = function(owner) {
	this.owner = owner;
	this.originalId;
	this.pickContainerId;
	this.selectedContainerId;
	this.selectButtonId;
	this.deSelectButtonId;
	this.cloneContainerId;
  	this.pickListArray;
	this.selectedListArray;

	this.objectType = "TransferlistObject";
}

IAJS.CONTROLLER.TransferlistObject.prototype.init = function() {
	this.originalId = this.owner.input.id;
  	this.pickContainerId = "pick_" + this.originalId;
	this.selectedContainerId = "select_" + this.originalId;
	this.selectOneButtonId = "selectOne_" + this.originalId;
	this.deSelectOneButtonId = "deSelectOne_" + this.originalId;
  	this.selectAllButtonId = "selectAll_" + this.originalId;
	this.deSelectAllButtonId = "deSelectAll_" + this.originalId;
	this.cloneContainerId = "cloneContainer_" + this.originalId;
	
  	this.pickListArray = new Array();
	this.selectedListArray = new Array();

	var div = document.createElement("DIV");
	YAHOO.util.Dom.setStyle(div, 'display', 'none');
	div.setAttribute("id",this.cloneContainerId);
  	var copy = this.owner.input.cloneNode(true);
	div.appendChild(copy);
  	this.owner.node.parentNode.appendChild(div);
	// ie forgets selected options on clone, so get them and put them on clone
	this.copySelectedOptions(this.owner.input,copy);

	try {
		this.owner.node.innerHTML = this._fromTemplate();
  	
		this.original = document.getElementById(this.originalId);
  		this.picker = document.getElementById(this.pickContainerId);
		this.selector = document.getElementById(this.selectedContainerId);
			
   		this.fill();
		
		YAHOO.util.Event.on(this.picker, "dblclick", this.selectOne, this, true);
		YAHOO.util.Event.on(this.selector, "dblclick", this.deSelectOne, this, true);
    	YAHOO.util.Event.on(this.selectOneButtonId, "click", this.selectOne, this, true);
		YAHOO.util.Event.on(this.deSelectOneButtonId, "click", this.deSelectOne, this, true);
		YAHOO.util.Event.on(this.selectAllButtonId, "click", this.selectAll, this, true);
		YAHOO.util.Event.on(this.deSelectAllButtonId, "click", this.deSelectAll, this, true);
		YAHOO.util.Event.on(this.pickContainerId, "click", this.checkButtons, this, true);
		YAHOO.util.Event.on(this.selectedContainerId, "click", this.checkButtons, this, true);
	} catch (e) {
		/*console.log(e);*/
	}
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.fill = function() {
	this.clear();
	for(i=0, l = this.original.options.length; i < l; i++){
  		var opt =  this.original.options[i];
		var obj = new Option(opt.text,opt.value);
		(opt.selected) ?  this.selector.options.add(obj) : this.picker.options.add(obj);
	}
	this.checkButtons();
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.clear = function() {
	while(this.picker.options.length != 0){
		this.picker.remove(this.picker.options.length-1);
	}

	while(this.selector.options.length != 0){
		this.selector.remove(this.selector.options.length-1);
	}
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.selectOne = function() {
    for(var i=0, l = this.picker.options.length;i<l;i++) {
		var opt = this.picker.options[i];
		if(opt.selected) {
			for(var j=0, ll = this.original.options.length; j < ll; j++){
				if(opt.value == this.original.options[j].value) this.original.options[j].selected = true;
			}
		}
	}
	this.fill();
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.selectAll = function() {
    for(var i=0, l=this.original.options.length;i<l;i++){
        this.original.options[i].selected = true;
	}
	this.fill();
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.deSelectOne = function() {
	for(var i=0, l=this.selector.options.length;i<l;i++) {
		var opt = this.selector.options[i];
		if(opt.selected) {
			for(var j=0;j<this.original.options.length;j++){
				if(opt.value == this.original.options[j].value) this.original.options[j].selected = false;
			}
		}	
	}
	this.fill();
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.deSelectAll = function() {
    for(var i=0, l= this.original.options.length;i<l;i++) {
        this.original.options[i].selected = false;
	}
	this.fill();
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.checkButtons = function(e) {
	target = (e) ? e.target.parentNode : false;
	status = false;

    this.enableButton(this.selectOneButtonId,this.picker.options.length);
	this.enableButton(this.selectAllButtonId,this.picker.options.length);

    this.enableButton(this.deSelectAllButtonId,this.selector.options.length);
	this.enableButton(this.deSelectOneButtonId,this.selector.options.length);
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.enableButton = function(id,bool) {
		obj = document.getElementById(id);
		(bool)?	obj.removeAttribute('disabled') : obj.setAttribute('disabled','disabled');
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype.copySelectedOptions = function(from,to) {
  for(var i=0, l =from.options.length;i<l;i++) {
		if(from.options[i].selected) to.options[i].selected = true;
	}
}
/**
 * @private
 */
IAJS.CONTROLLER.TransferlistObject.prototype._fromTemplate = function() {
	var tagReplace = {
		"selectAll"  : '<button id="selectAll_{id}" type="button" title="{selectall}">&gt;&gt;</button>',
		"selectOne" : '<button id="selectOne_{id}" title="{selectone}" type="button">&gt;</button>',
		"deselectAll" : '<button id="deSelectOne_{id}" type="button" title="{deselectone}" disabled="disabled">&lt;</button>',
		"deselectOne" : '<button id="deSelectAll_{id}" type="button" title="{deselectall}" disabled="disabled">&lt;&lt;</button>',
		"selectall" : LOCALIZE.messages.TRANSFER_SELECTALL,
		"selectone" : LOCALIZE.messages.TRANSFER_SELECTONE,
		"deselectone" : LOCALIZE.messages.TRANSFER_DESELECTONE,
		"deselectall" : LOCALIZE.messages.TRANSFER_DESELECTALL,
		"id" : this.owner.input.id
		};
	var template = this._getTemplate();
	
	for(key in tagReplace){
		var template1split = template.split("{"+key+"}");
		template = template1split.join(tagReplace[key]);
	}
	
	return template;
}

IAJS.CONTROLLER.TransferlistObject.prototype._getTemplate = function() {
	
	var l = (typeof this.owner != 'undefined' && typeof this.owner.containerLabel != 'undefined')? this.owner.containerLabel.innerHTML || "choice" : "choice"; 
	var i=0;
	var val = [];
	val[i++] = '<div class="inputElement transfer">';
	val[i++] = '<div class="inputCaption">';
	val[i++] = '<label class="label" for="pick_{id}">' + l + '<span class="required">*</span></label>';
	val[i++] = '</div>';
	val[i++] = '<div class="inputControl">';
	val[i++] = '<div class="controls">';
	val[i++] = '<select name="pick_{id}" id="pick_{id}" multiple="multiple" size="8">';
	val[i++] = '</select>';
	val[i++] = '</div>';
	val[i++] = ' <div class="controls actions">';
	val[i++] = '{selectAll}{selectOne}{deselectAll}{deselectOne}';
	val[i++] = '</div>';
	val[i++] = '<div class="controls">';
	val[i++] = ' <select name="select_{id}" id="select_{id}" multiple="multiple" size="8">';
	val[i++] = ' </select>';
	val[i++] = '</div>';
	val[i++] = '</div>';
	val[i++] = '</div>';
		
	return val.join(" ");	
}		/**
 * The URL Controller
 * 
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.BaseController
 * @param {HTMLelement} node The eltype element to create the controller for.
 */
IAJS.CONTROLLER.Url = function(node) {
	this.node = node;
	this.objectType = "Url";
	this.css = {controls: 'controls'};
	this.responseItem = new IAJS.response.Item(this);	
	this.events = new IAJS.EventList(this);
	/**
	 * Fires after the value is changed.
	 * @name onChange
	 * @memberOf IAJS.CONTROLLER.Url
	 */	
	this.events.add("onChange");
	/**
	 * Fires after the controller is enable state is changed.
	 * @name contentChange
	 * @memberOf IAJS.CONTROLLER.Url
	 */	
	this.events.add("onEnableChange");
	/**
	 * Fires after the result of the validation is changed.
	 * @name validationResultChange
	 * @memberOf IAJS.CONTROLLER.Url
	 */	
	this.events.add("validationResultChange");
	/**
	 * Fires after the value is validated
	 * @name validate
	 * @memberOf IAJS.CONTROLLER.Url
	 */	
	this.events.add("validate");	
}
YAHOO.extend(IAJS.CONTROLLER.Url, IAJS.CONTROLLER.BaseController);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Url.prototype.init =  function() {
	if(this.node) {
		var controls = YAHOO.util.Dom.getElementsByClassName(this.css.controls,"div",this.node)[0]; 
		this.input = controls.getElementsByTagName("input", controls)[0];		
		this.initAttribute();
		if(!this.getAttr('allowedScheme')) this.setAttr('allowedScheme','http, https'); 	  // default allowed shemes
		YAHOO.util.Event.on(this.input, "blur", this.validate, this, true);
	}
	//
};
/**
 * Called by bootstrap after initializing the controller
 */
IAJS.CONTROLLER.Url.prototype.hookAfterInit = function() {
    this.validate();
};

IAJS.CONTROLLER.Url.prototype.hookBeforeSubmit = function() {
    if (this.validationCode == IAJS.RESPONSE.FALLTHROUGH && !this.elattr['isOptional']) {
      this.validationCode = IAJS.RESPONSE.MANDATORY;
	}
	this.responseAction();
};

IAJS.CONTROLLER.Url.prototype.validate = function() {
	var v = this.validationCode;
	var urlString = this.input.value;
	urlString = urlString.toStructuredUrl(this.elattr['assumeScheme']);
	this.validationCode = IAJS.VALIDATION.url(urlString, this.elattr['allowedScheme']);
	this.events.fire('validate');
	this.responseAction();
	// if the validationCode is changed trigger validation listeners 
	if (v != this.validationCode) this.events.fire('validationResultChange');
	// only trigger onChange value change compared to previous
	if (this.previousValue && this.previousValue != this.input.value) this.events.fire('onChange');
	this.previousValue = this.input.value;	
};

IAJS.CONTROLLER.Url.prototype.responseAction = function() {
	switch(this.validationCode) {
	  case IAJS.RESPONSE.OK:
	  	this.responseItem.clear();
		break;
	  case IAJS.RESPONSE.INVALID:
	  	this.responseItem.error(LOCALIZE.messages.URL_INVALID);
		break;
	  case IAJS.RESPONSE.MANDATORY:
	  	this.reponseItem.error(LOCALIZE.messages.URL_MANDATORY)
        break;
	  case IAJS.RESPONSE.FALLTHROUGH:
	  default:
		this.responseItem.clear();
	}
};
/**
 * Indicate if the controller can be inside a HTML form element 
 */
IAJS.CONTROLLER.Url.prototype.getCheckInsideForm = function(){return true;}
/**
 * The VAT Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.VatBase
 * @param {HTMLelement} node The eltype element to create the controller for.
 */
IAJS.CONTROLLER.Vat = function(node) {
	this.node = node;
	this.countryElm;	// HTMLelement that hold country value
	this.objectType = "Vat";
}

YAHOO.extend(IAJS.CONTROLLER.Vat, IAJS.CONTROLLER.VatBase);
/**
 * Initialization of the controller
 */
IAJS.CONTROLLER.Vat.prototype.init = function() {
	if(this.node) {
		IAJS.CONTROLLER.Vat.superclass.constructor.call(this, this.node);
		IAJS.CONTROLLER.Vat.superclass.init.call(this, this.node);
		this.countryElm = YAHOO.util.Dom.getElementsBy(function(el){return true},"select",this.node)[0];
		this.initAttribute(); 
		if (this.hasResponse()) {
			//hook change event
			YAHOO.util.Event.on(this.countryElm, "change", this.validate, this, true);
		}
	}
}
/**
 * return country property 
 */
IAJS.CONTROLLER.Vat.prototype.getCountry = function() {
 	return (this.countryElm)? this.countryElm.options[this.countryElm.selectedIndex].value : null;
};
/**
 * The Belgium VAT Controller
 *
 * @author Internet Architects BVBA
 * @copyight 2007-2008
 * @version 1.0.5
 */
 
/**
 * @constructor
 * @base IAJS.CONTROLLER.Vat
 * @param {HTMLelement} node The eltype element to create the controller for.
 */

IAJS.CONTROLLER.VatBelgium = function(node) {
	this.node = node;
	this.objectType = "VatBelgium";
}

YAHOO.extend(IAJS.CONTROLLER.VatBelgium, IAJS.CONTROLLER.VatBase);

IAJS.CONTROLLER.VatBelgium.prototype.init = function() {
	if (this.node){
		IAJS.CONTROLLER.VatBelgium.superclass.constructor.call(this, this.node);
		IAJS.CONTROLLER.VatBelgium.superclass.init.call(this, this.node);
		this.initAttribute(); 
	}
}
/**
 * return country property 
 */
IAJS.CONTROLLER.VatBelgium.prototype.getCountry = function() {
	return "BE"; 
}/**
 * Javascript framework for design patterns
 * 
 * @fileoverview Bootstrap to initalize eltype controllers
 *   
 * @author Internet Architects BVBA
 * @version 1.0.5
 * @copyight 2007-2008
 */

/**
 * bootstrap
 * @class IA
 */
var IA = (function () {
	return {
		bootstrap: function() {
			IAJS.controllerManager.parse(document);
		}
	}
})();
/**
 * use debugging if provided 
 */
try {if(typeof IAdebug != 'undefined' && IAdebug.enableDebug == true){YAHOO.util.Event.onDOMReady(IAdebug.init);}}catch(e){};
/**
 * start bootstrap when DOM is ready  
 */
if(IAJS && IAJS.CONFIG){
	YAHOO.util.Event.onDOMReady(IA.bootstrap);
};
