/* ---------------------------------
  @ CingoKit.Form.element

  Registers a form elemnt with a specific CingoKit.Form object.
  Provide functionality at the form element level

  Purposes of this object:
  - register the form element
  - provide access/storage/validation at the form element level
----------------------------------- */
// dialog constructor
CingoKit.Form.Element = function ( properties )
{
	// register baseclass
	this._class = CingoKit.Form.Element;
	// initialize
	this.init(properties);
}


// main functions
CingoKit.Form.Element.prototype = {

	init : function( properties )
	{
		// store properties for this dialog
		this.applyObject(properties);

		// set reference within element back to obj
		this.elem._obj = this;

		// set flag to know that this element has been registered
		this.elem._registered = true;

		// if preset element is filled in, unfocus the field
		if (!this.isElementValueOriginal()) {
			if (this.isTextElement() && this.getElementValue().length > 0) {
				this.focusTextElement();
			};
		};

		/*
		 * Establish validation settings
		 */
		this.getValidationSettings();

		/*
		 * Handle initialization
		 */
		if (this.isTextElement()) {

			if (!this.isFileElement()) {

				// store if this is a password element
				this._ispassword = this.isPasswordElement();

				// set handlers
				this.setTextHandlers();

				// overload handlers
				this.overloadHandler(this.elem, 'onkeypress');

				// set up default keypress func on textfields
				this.elem.onkeypress = function(e)
				{
					if (window.event) {
						var e = window.event;
						var keycode = e.keyCode;
						e.cancelBubble=true;
					} else if (e) {
						var keycode = e.which;
						if (e.stopPropagation) { e.stopPropagation() }
					} else {
						return true;
					};

					// if NOT pressing enter, focus the field and remove error styling
					if (keycode != 13) { this._obj.focusTextElement() };
				};

				// test to see if autocomplete is enabled...
				var useAutoComplete = getNodeAttribute(this.elem, "useautocomplete");
				if (!isNull(useAutoComplete)) {

					// split the values
					var arr = useAutoComplete.split(',');
					if (arr.length > 1) {
						var xfa = arr[0];
						var allowMultipleEntries = arr[1];
					} else {
						var xfa = useAutoComplete;
						var allowMultipleEntries = false;
					};

					// enable it...
					this.enableAutoComplete({
						'xfa' : xfa,
						'allowMultipleEntries' : allowMultipleEntries
					});
				};

				// test to see if username checking is enabled...
				var useUsernameCheck = getNodeAttribute(this.elem, "useusernamecheck");
				if (!isNull(useUsernameCheck)) {

					// split the values
					var arr = useUsernameCheck.split(',');
					if (arr.length > 1) {

						var xfa = arr[0];
						var container = arr[1];
						var messages = arr[2];

						this.enableUsernameCheck({
							'xfa' : xfa,
							'container' : container
						});

					};
				};

			};


			/*
			 * Establish originalvalue if applicable
			 */
			if (this.getElementValue().length == 0) {
				if (this.hasOriginalValue()) {

					// switch types if password
					if (this._ispassword) {

						// first, erase the password
						this.elem.value = "";

						// next, create the overlay and show it - always on first load
						this.createPasswordOverlay();
						this.showPasswordOverlay();

					};

					this.setElementValue( this.getOriginalValue() );
				};
			};

		} else if (this.isSelectElement()) {

			this.setSelectHandlers();

		} else if (this.isCheckboxElement()) {

			this.setCheckboxHandlers();

		};

		/*
		 * If this element is part of a modal nav, find the modalcontent
		 */
		if (this.mgr.inModalNav) {

			// find the parent...
			var parent = this.elem;

			do { parent = parent.parentNode }
			while ( !hasElementClass( parent, 'modalcontent') && (parent != document.body) );

			// set the modal content in this form element object to the parent modalcontent <div>
			this._modalcontent = (hasElementClass( parent, 'modalcontent')) ? parent : null;

		};

	},

	destroy : function()
	{
		this.mgr.destroyElement(this);
	},


	/**
	 * Enable auto-complete on text form elements
	 */
	enableAutoComplete : function( obj )
	{
		if ( this.isTextElement() ) {

			// append on the mgr to the object
			obj.mgr = this;

			// next, set up the autocomplete passing on obj
			this._autoComplete = new CingoKit.Form.AutoComplete(obj);

		} else {
			logError("Can't enable auto-complete - element isn't a text field");
		};
	},


	/**
	 * Enable username checking on text form elements
	 */
	enableUsernameCheck : function( obj )
	{
		if ( this.isTextElement() ) {

			// append on the mgr to the object
			obj.mgr = this;

			// next, set up the username object, passing on obj
			this._usernameCheck = new CingoKit.Form.Username(obj);

		} else {
			logError("Can't enable username checking - element isn't a text field");
		};
	},


	/**
	 * Establish click handlers for button elements
	 */
	setClickHandler : function( func )
	{
		if (this.isButtonElement()) {
			this.elem.onclick = func;
		};
	},


	/**
	 * Establish enter handler for text elements
	 */
	setEnterHandler : function( func )
	{
		if (this.isTextElement()) {

			this.elem.onkeypress = func;
			this.overloadHandler(this.elem, 'onkeypress');

			this.elem.onkeypress = function(e)
			{
				if (window.event) {
					var e = window.event;
					var keycode = e.keyCode;
					e.cancelBubble=true;
				} else if (e) {
					var keycode = e.which;
					if (e.stopPropagation) { e.stopPropagation() }
				} else {
					return true;
				};

				// if NOT pressing enter, focus the field and remove error styling
				if (keycode == 13) {
					this._onkeypress();
					return false;
				} else {
					this.onfocus();
				};
			};
		};
	},


	/*
	 * Activation functions for text-based form elements
	 */
	setTextHandlers : function()
	{
		var self = this;
		connect(this.elem, 'onfocus', self, 'focusTextElement');
		connect(this.elem, 'onblur', self, 'unfocusTextElement');
	},

	focusTextElement : function()
	{
		// first, unerror the element
		this.unerrorElement();

		// hide the error message if shown
		this.hideMessage();

		if (this.isTextElement()) {

			// if it's a textfield, clear the value and add "active' to it's classname
			this.activateElement();
			if (this.isElementValueOriginal()) { this.elem.value = "" };

			// switch types if password
			if (this._ispassword) {
				this.hidePasswordOverlay();
			};
			
			// fire off any signals attached
			if (!isUndefinedOrNull(MochiKit.Signal)) {
				signal(this, 'focusTextElement');
			};

		};
	},

	unfocusTextElement : function()
	{
		if (this.isTextElement()) {

			// see if anything changed, if not then reset back to faded appearance
			if (this.getElementValue().length == 0) {

				this.deactivateElement();

				if (this.hasOriginalValue()) {

					// switch types if password
					this.showPasswordOverlay();

					this.setElementValue( this.getOriginalValue() );
				};
			};
			
			// fire off any signals attached
			if (!isUndefinedOrNull(MochiKit.Signal)) {
				signal(this, 'focusTextElement');
			};

		};
	},




	/*
	 * Activation functions for misc form elements
	 */
	setSelectHandlers : function()
	{
		var self = this;
		connect(this.elem, 'onchange', self, 'focusSelectElement');
	},

	focusSelectElement : function()
	{
		// first, unerror the element
		this.unerrorElement();

		// hide the error message if shown
		this.hideMessage();
	},





	/*
	 * Activation functions for checkbox form elements
	 */
	setCheckboxHandlers : function()
	{
		var self = this;
		connect(this.elem, 'onclick', self, 'focusCheckboxElement');
	},

	focusCheckboxElement : function()
	{
		// first, unerror the element
		this.unerrorElement();

		// hide the error message if shown
		this.hideMessage();
	},





	/*
	 * Activation functions for password form elements
	 */
	createPasswordOverlay : function()
	{
		this.passwordOverlay = SPAN({'class' : 'passwordoverlay', 'style' : 'display:none'}, this.getOriginalValue());
		this.elem.parentNode.insertBefore(this.passwordOverlay, this.elem);

		// set onclick handler
		this.passwordOverlay._obj = this;
		this.passwordOverlay.onmousedown = function()
		{
			this._obj.focusTextElement();
			this._obj.elem.select();
		};
	},

	hidePasswordOverlay : function()
	{
		if (!isUndefinedOrNull(this.passwordOverlay)) {
			this.passwordOverlay.style.display = 'none';
		}
	},

	showPasswordOverlay : function()
	{
		if (!isUndefinedOrNull(this.passwordOverlay)) {
			this.passwordOverlay.style.display = 'block';
		};
	},




	/*
		validation settings:
		- length (value length must be equal to or greater than number)
		- char (value must have at least one of the included characters)
		- selindex/selmultiple (used with select menus - current menu must not equal index value set or >0 selected)
		- check (boolean check using 0 or 1 to check status of a checkbox)
		- radio (value of the value attribute of currently selected radio button must equal that which is set)
	*/
	getValidationSettings : function()
	{
		var require = getNodeAttribute(this.elem, 'require');
		this._require = (require != null);

		var requireIfUsed = getNodeAttribute(this.elem, 'requireIfUsed');
		this._requireIfUsed = (requireIfUsed != null);

		if (this._require || this._requireIfUsed) {

			var attribute = (this._require) ? require : requireIfUsed;

			// parse immediately
			if (attribute.indexOf("[")!=-1 && attribute.indexOf("]")!=-1) {
				this._validation = eval(attribute);
				//log("Evaluation for element (" + this.elem.name + ")", this._validation, "(" + this._validation.length + ")");
			} else {
				this._validation = this.parseScenerio( attribute );
				//log("Parsing for element (" + this.elem.name + ")", this._validation, "(" + this._validation.length + ")");
			}

		};
	},
	

	validateElement : function()
	{
		//logDebug("----------------------------------");
		//logDebug("Run validation on element (" + this.elem.name + ")");

		// first, if the element is part of an autocomplete, clear it
		if (!isUndefinedOrNull( this._autoComplete )) {
			this._autoComplete.clearList();
		};

		var elemIsValid = true;

		// if element is visible, continue with the validation test
		if (this._require || this._requireIfUsed) {

			//logDebug("Validation required");

			// first, if element is not visible, just skip and assume it's valid...
			if (this.isElementVisible()) {

				//logDebug("     Processing validation: " + this._validation + " / scenerios: " + this._validation.length);

				for (var i=0; i<this._validation.length; i++) {

					// only proceed if scenerio is a valid scenerio array
					var scenerio = this._validation[i];

					//logDebug("          Scenerio: " + scenerio);

					if (this.validateScenerio(scenerio)) {

						var scenerioIsValid = this.validateElementScenerio(scenerio);

						if (!scenerioIsValid) {

							// flag as invalid
							elemIsValid = false;

							// if invalid, test only the first element scenerio on this element
							break;

						};

					};
				};

			} else {
				//log("Validation cancelled - " + this.elem.name, "is not visible");
			};

		} else {
			//log("No validation needed");
		};

		return elemIsValid;
	},

	invalidateElement : function( errormessage )
	{
		// error out this element
		this.errorElement();

		// reveal the error message
		this.revealMessage( errormessage, 'error' );

		// if this form element (and parent form) is part of a modalnav, send it to the appropriate modalcontent
		if (!isUndefinedOrNull(this._modalcontent)) {
			this._modalcontent._obj.setAsCurrent();
		};
	},

	validateScenerio : function( scenerio )
	{
		// first, check to see if it's an array
		var isvalid = (typeof(scenerio) == 'object' && scenerio.length > 1);
		return isvalid;
	},

	validateElementScenerio : function( scenerio )
	{
		var scenerioIsValid = true;

		var value = this.getElementValue();

		// if this is a requireIfUsed and it's a text value and it's empty, ignore validation
		if (this._requireIfUsed && this.isTextElementValueEmpty()) {
			return true;
		};
		
		if (scenerio.length > 1 ) {

			// parse out the scenerio values
			var testmethod = scenerio[0];
			var testvalue = scenerio[1];
			var errormessage = scenerio[2];

		};

		if (scenerio.length >= 3) {

			// set the container
			this.setMessageContainer( scenerio[3] );

		};

		//logDebug("               testmethod: " + testmethod);
		//logDebug("               testvalue: " + testvalue);
		//logDebug("               errormessage: " + errormessage);

		// if the testmethod is selIndex but the type is a select-multiple (size>0) then reset as selMultiple
		if (testmethod == "selindex" && this.getElementType() == "select-multiple") {
			testmethod = "selmultiple";
			//logDebug("                    testmethod OVERWRITTEN to selmultiple");
		};

		// first, test to make sure the current value is not the default value
		if (this.isElementValueOriginal()) {

			// go ahead and error it out...
			this.errorElement();
			scenerioIsValid = false;

		} else {

			switch (testmethod)
			{
				case "length":
					scenerioIsValid = (value.length >= testvalue);
					// fill in with default value if present
					if (!scenerioIsValid && this.hasOriginalValue()) {
						this.setElementValue( this.getOriginalValue() );
					};
					break;

				case "char":
					if (!this.isElementValueOriginal() && value.length >= 1 ) {
						scenerioIsValid = (value.indexOf(testvalue) != -1);
					};
					break;

				case "nochar":
					if (!this.isElementValueOriginal() && value.length >= 1 ) {
						scenerioIsValid = (value.indexOf(testvalue) == -1);
					};
					break;

				case "selindex":
					scenerioIsValid = (value != testvalue);
					break;

				case "selmultiple":
					scenerioIsValid = value.length > 0;
					break;

				case "check":
					scenerioIsValid = (value == testvalue);
					break;

				case "regex":
					scenerioIsValid = testvalue.regex.test(value);
					break;

				default:
					break;
			};
		};

		if (!scenerioIsValid) {

			// error the element out and invalidate it
			this.invalidateElement(errormessage);

		};

		if (scenerioIsValid) {
			//log("Validation passed!");
		} else {
			logError("Validation failed");
		};

		return scenerioIsValid;

	},



	convertOriginalValue : function()
	{
		if (this.isElementValueOriginal()) {
			this.setElementValue("");
		};
	},


	/**
	 * Error handling
	 */
	errorElement : function()
	{
		if (!this.isFileElement()) {
			addElementClass(this.elem, 'error');
		};
	},
	unerrorElement : function()
	{
		if (!this.isFileElement()) {
			removeElementClass(this.elem, 'error');
			// if this is a text element, erase value if it's the default
			if (this.isElementValueOriginal()) {
				this.unfocusTextElement();
			};
		};
		
		// mark the form as available every time an errored element is focused
		this.mgr.markAsAvailable();
	},


	// message containers
	setMessageContainer : function( value )
	{
		if (isUndefinedOrNull(this.getMessageContainer())) {
			
			if (typeof(value) == "string") {
				this._messageContainer = $(value);
			} else {
				if (!isUndefinedOrNull(value)) {
					this._messageContainer = value;
				} else {
					logError("ERROR: invalid element value provided in setting element messageContainer");
				};
			};
		};
	},

	getMessageContainer : function()
	{
		return this._messageContainer;
	},

	revealMessageContainer : function()
	{
		showElement( this.getMessageContainer() );
	},

	hideMessageContainer : function()
	{
		hideElement( this.getMessageContainer() );
	},


	// message elements
	setMessageElement : function( msgclass )
	{
		var container = this.getMessageContainer();

		if (!isUndefinedOrNull(container)) {

			// get current elements if present
			var msgelement = getFirstElementByTagAndClassName('h1', msgclass, container);

			// create the element and set it...
			if (isUndefinedOrNull(msgelement)) {
				var elem = this.createMessage(msgclass);
				appendChildNodes(container, elem);
			} else {
				var elem = msgelement;
			};

			// set the reference...
			container._message = elem;

		};
	},

	getMessageElement : function()
	{
		var ref = null;
		var container = this.getMessageContainer();

		if (!isUndefinedOrNull(container)) {
			var message = container._message;
			ref = !isUndefinedOrNull(message) ? message : null;
		};

		return ref;
	},


	// message access functions
	createMessage : function( msgclass )
	{
		var elem = H1( {'class' : msgclass }, "&nbsp;" );
		return elem;
	},

	setMessage : function(msg)
	{
		var message = this.getMessageElement();

		if (!isNull( message )) {
			message.innerHTML = msg;
		};
	},

	revealMessage : function( msg, msgclass )
	{
		var container = this.getMessageContainer();

		if (isNull( this.getMessageElement() )) {
			this.setMessageElement( msgclass );
		};

		this.setMessage(msg);
		var message = this.getMessageElement();

		// set the visible class on the form container
		addElementClass(container, 'autoheight');

		//setOpacity(message, 1);
		showElement(message);
	},

	hideMessage : function()
	{
		var container = this.getMessageContainer();
		var message = this.getMessageElement();

		if (!isNull( message )) {
			hideElement(message);
		};

		// remove the visible class from the form container
		if (!isUndefinedOrNull( container )) {
			removeElementClass(container, 'autoheight');
		};
	},


	// element access functions
	activateElement : function()
	{
		if ( !hasElementClass(this.elem, 'active') ) {
			addElementClass(this.elem, 'active');
		};
	},

	deactivateElement : function()
	{
		removeElementClass(this.elem, 'active');
	},

	hasOriginalValue : function()
	{
		var value = getNodeAttribute(this.elem, 'originalvalue');
		return (value != null && value.length > 0);
	},

	getOriginalValue : function()
	{
		return getNodeAttribute(this.elem, 'originalvalue');
	},

	isElementValueOriginal : function()
	{
		var isdefault = false;
		if (this.hasOriginalValue()) {
			if (this.isTextElement() && this.getElementValue() == this.getOriginalValue()) {
				isdefault = true;
			};
		};
		return isdefault;
	},

	isTextElementValueEmpty : function()
	{
		if (this.isTextElement()) {
			var isempty = (this.getElementValue().length == 0);
		} else {
			var isempty = false;
		};
		return isempty;
	},

	getElementValue : function()
	{
		var type = this.getElementType();
		var value = null;

		switch(type)
		{
			case "checkbox":
				var value = this.elem.checked;
				break;

			case "select-multiple":
				var value = new Array;
				var selected = this.getSelectedFromCollection();
				if (!isNull(selected)) {
					for (var i=0; i<selected.length; i++) {
						var option = selected[i];
						value.push( option.value );
					};
				};
				break;

			default:
				var selected = this.getSelectedFromCollection();
				if (!isNull(selected)) {
					var value = selected.value;
				};
				break;
		};

		return value;
	},
	getElementsFromCollection : function()
	{
		var type = this.getElementType();

		switch(type)
		{
			case "radio":
				// radio buttons must be approached at the nodeList level
				var selected = this.mgr.elem[ this.getElementName() ];
				break;

			default:
				var selected = this.elem;
				break;
		};

		if (isUndefinedOrNull(selected)) {
			var selected = null;
		};

		return selected;
	},
	getElementFromCollectionByName : function( name )
	{
		var type = this.getElementType();

		switch(type)
		{
			case "radio":
				// radio buttons must be approached at the nodeList level
				var nodeList = this.mgr.elem[ this.getElementName() ];

				for (var i=0; i<nodeList.length; i++) {
					var option = nodeList[i];
					if (option.name == name) {
						var selected = option;
						break;
					};
				};
				break;

			default:
				var selected = this.elem;
				break;
		};

		if (isUndefinedOrNull(selected)) {
			var selected = null;
		};

		return selected;
	},
	
	getElementFromCollectionByValue : function( value )
	{
		var type = this.getElementType();

		switch(type)
		{
			case "radio":
				// radio buttons must be approached at the nodeList level
				var nodeList = this.mgr.elem[ this.getElementName() ];

				for (var i=0; i<nodeList.length; i++) {
					var option = nodeList[i];
					if (option.value == value) {
						var selected = option;
						break;
					};
				};
				break;

			default:
				var selected = this.elem;
				break;
		};

		if (isUndefinedOrNull(selected)) {
			var selected = null;
		};

		return selected;
	},
	
	getEscapedElementValue : function()
	{
		return escape(this.getElementValue());
	},

	setElementValue : function( value )
	{
		// only do this if the value is not null or undefined
		if (!isUndefinedOrNull(value)) {
			
			switch( this.getElementType() )
			{
				case "checkbox":
						this.elem.checked = (typeof(value) == "boolean") ? value : false;
						break;
	
				case "radio":
					// radio buttons must be approached at the nodeList level
					var nodeList = this.mgr.elem[ this.getElementName() ];
					for (var i=0; i<nodeList.length; i++) {
						var option = nodeList[i];
						if (option.value == value) {
							option.checked = true;
							break;
						};
					};
				break;
	
				case "select-one":
					var options = this.elem.options;
					for (var i=0; i<options.length; i++) {
						var option = options[i];
	
						if (option.value == value) {
							option.selected = true;
							break;
						};
					};
					break;
	
				default:
					this.elem.value = value;
					break;
			};
			
		};
	},
	
	setElementValueAsOriginal : function()
	{
		if (this.isTextElement() && this.hasOriginalValue()) {
			this.setElementValue( this.getOriginalValue() );
		} else {
			this.setElementValue("");
		};
	},

	getSelectedFromCollection : function()
	{
		var type = this.getElementType();

		switch(type)
		{
			case "radio":
				// radio buttons must be approached at the nodeList level
				var nodeList = this.mgr.elem[ this.getElementName() ];

				for (var i=0; i<nodeList.length; i++) {
					var option = nodeList[i];
					if (option.checked) {
						var selected = option;
						break;
					};
				};
				break;

			case "select-one":
				var options = this.elem.options;
				for (var i=0; i<options.length; i++) {
					var option = options[i];
					if (this.elem.selectedIndex == i) {
						var selected = option;
						break;
					};
				};
				break;

			case "select-multiple":
				var selected = new Array;
				var options = this.elem.options;
				for (var i=0; i<options.length; i++) {
					var option = options[i];
					if (option.selected) {
						selected.push( option );
					};
				};
				break;

			default:
				var selected = this.elem;
				break;
		};

		if (isUndefinedOrNull(selected)) {
			var selected = null;
		};

		return selected;
	},



	// store value
	setStoredValue : function()
	{
		this.__storedValue = this.getElementValue();
	},

	getStoredValue : function()
	{
		return this.__storedValue;
	},


	clearAndResetElement : function()
	{
		if (this.isTextElement()) {
			this.elem.value = "";
		};

		this.unfocusTextElement();
	},

	disableElement : function()
	{
		this.elem.disabled = true;
		if ( !this.isButtonElement() && !this.isFileElement() && !this.isRadioElement() && !this.isCheckboxElement() ){
			addElementClass(this.elem, 'disabled');
		};
	},

	enableElement : function()
	{
		this.elem.disabled = false;
		removeElementClass(this.elem, 'disabled');
		removeElementClass(this.elem, 'disabledfield');
	},

	getElementName : function()
	{
		return (this.elem.name || null);
	},

	getElementType : function()
	{
		var type = this.elem.type;

		// if the type is a select, but size>0 then reset as select-multiple
		if (type == "select-one" && getNodeAttribute(this.elem, 'size') > 1) {
			type = "select-multiple";
		}

		// if undefined, member might not have a type
		if (isUndefinedOrNull( type )) {
			type = this.elem.nodeName.toLowerCase();
		}

		return type;
	},

	getElementTag : function()
	{
		return this.elem.nodeName.toLowerCase();
	},



	/*
	 * Type tests
	 */
	isTextElement : function()
	{
		return (this.getElementType() == "text" || this.getElementType() == "textarea" || this.getElementType() == "password" || this.getElementType() == "file");
	},

	isButtonElement : function()
	{
		return (this.getElementType() == 'image' || this.getElementType() == 'submit' || this.getElementType() == 'button')
	},

	isRadioElement : function()
	{
		return (this.getElementType() == "radio");
	},

	isCheckboxElement : function()
	{
		return (this.getElementType() == "checkbox");
	},

	isFileElement : function()
	{
		return (this.getElementType() == "file");
	},

	isPasswordElement : function()
	{
		return (this.getElementType() == "password");
	},

	isSelectElement : function()
	{
		return (this.getElementType() == "select-one" || this.getElementType() == "select-multiple");
	},



	/*
	 * Status tests
	 */
	isElementVisible : function()
	{
		var isvisible = true;
		var parent = this.elem;

		if (this.elem.style.display != 'none' && this.elem.style.visiblity != 'hidden') {

			do {
				parent = parent.parentNode;
				if (parent.style.display == 'none' || parent.style.visibility == 'hidden') {
					isvisible = false;
					break;
				}
			} while (parent != document.body)

		} else {
			isvisible = false;
		};
		return isvisible;
	},

	isElementDisabled : function()
	{
		return (this.elem.disabled == "disabled" || this.elem.disabled == true || hasElementClass(this.elem, 'disabled'));
	},

	isElementEnabled : function()
	{
		return (!this.isElementDisabled());
	},




	/*
	 * Parse validation shortcut conversion
	 */
	parseScenerio : function( scenerio )
	{
		// if a shortcut, convert it
		if (typeof(scenerio) == 'string') {

			// split it
			var arr = scenerio.split(',');

			// set the shortcut up
			if (arr.length > 0) {

				// split up the array
				validationMethod = arr[0];
				messageContainer = arr[1];

			};

			// reset & reuse
			var regex = null;
			var arr = new Array();
			var mode = modifier = msg = null;
			var mode2 = modifier2 = msg2 = null;

			switch( validationMethod )
			{

				case 'name':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a name.';
					break;

				case 'firstname':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a first name.';
					break;

				case 'lastname':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a last name.';
					break;

				case 'username':
					var mode = "regex"
					var modifier = { 'regex' : /^[A-Za-z][A-Za-z0-9_\.]{1,22}[A-Za-z0-9]$/ };
					var msg = 'Usernames must only contain letters, numbers, underscores(_) and periods (.).<br /><br />Usernames must also be between 2 and 24 characters in length and must begin with a letter and end with a letter or number.';
					break;

				case 'password':
					var mode = 'length';
					var modifier = 5;
					var msg = 'Please enter a valid password of at least five characters length.';
					break;

				case 'password_confirm':
					var mode = 'length';
					var modifier = 5;
					var msg = 'Please enter a valid confirmation password.';

					var mode2 = 'nochar';
					var modifier2 = ' ';
					var msg2 = 'Spaces are not allowed within a password.';
					break;

				case 'email':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter an email address.';

					var mode2 = 'char';
					var modifier2 = '@';
					var msg2 = 'Please enter a valid email address.';

					var mode3 = 'char';
					var modifier3 = '.';
					var msg3 = 'Please enter a valid email address.';
					break;
					
				case 'email_alternate':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter an alternate email address.';

					var mode2 = 'char';
					var modifier2 = '@';
					var msg2 = 'Please enter a valid alternate email address.';

					var mode3 = 'char';
					var modifier3 = '.';
					var msg3 = 'Please enter a valid alternate email address.';
					break;

				case 'email_business':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a business email address.';

					var mode2 = 'char';
					var modifier2 = '@';
					var msg2 = 'Please enter a valid business email address.';

					var mode3 = 'char';
					var modifier3 = '.';
					var msg3 = 'Please enter a valid business email address.';
					break;

				case 'email_personal':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a personal email address.';

					var mode2 = 'char';
					var modifier2 = '@';
					var msg2 = 'Please enter a valid personal email address.';

					var mode3 = 'char';
					var modifier3 = '.';
					var msg3 = 'Please enter a valid personal email address.';
					break;

				case 'phone_work':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a work phone number.';
					break;

				case 'phone_home':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a home phone number.';
					break;

				case 'phone_mobile':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a mobile phone number.';
					break;

				case 'address':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter an address.';
					break;

				case 'address_work':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a work address.';
					break;

				case 'address_home':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a home address.';
					break;

				case 'city':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a city.';
					break;

				case 'state':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please choose a state.';
					break;

				case 'zipcode':
//					var mode = 'length';
//					var modifier = 5;
//					var msg = 'Please enter a valid 5-digit zip code.';
					
					var mode = "regex"
					var modifier = { 'regex' : /^\d{5}$/ };
					var msg = 'Please enter a valid 5-digit zip code1.';
					break;

				case 'zipcode_work':
					var mode = 'length';
					var modifier = 5;
					var msg = 'Please enter a valid work zip code.';
					break;

				case 'zipcode_home':
					var mode = 'length';
					var modifier = 5;
					var msg = 'Please enter a valid home zip code.';
					break;

				case 'month_mm':
					var mode = 'length';
					var modifier = 2;
					var msg = 'Please enter a two-digit month.';
					break;

				case 'day_dd':
					var mode = 'length';
					var modifier = 2;
					var msg = 'Please enter a two-digit day.';
					break;

				case 'birthday_month':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please choose a birthday month.';
					break;

				case 'security_question':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please choose a security question.';
					break;

				case 'security_answer':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter an answer to the security question.';
					break;

				case 'credit_card_type':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please select the credit type.';
					break;

				case 'credit_card_number':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a valid credit card number.';
					break;

				case 'credit_card_cvv':
					var mode = 'length';
					var modifier = 3;
					var msg = 'Please a valid three or four-digit CVV code.';
					break;

				case 'credit_card_expmonth':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please select the credit card expiration month.';
					break;

				case 'credit_card_expyear':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please select the credit card expiration year.';
					break;
					
				case 'liveedit':
					var mode = 'length';
					var modifier = 1;
					var msg = 'Please enter a value into the field.';
					break;
				case 'org_type':
					var mode = 'selindex';
					var modifier = 0;
					var msg = 'Please choose an Organization Type.';
					break;	
				case 'website':
					var mode = "regex"
					var modifier = { 'regex' : /[a-z0-9]{1,}\.[a-z0-9]{2,5}($|\/)/i };
					var msg = 'Please enter a valid web site address.';

				default:
					break;

			};

			// build the array
			if (!isNull(mode) && !isNull(modifier) && !isNull(msg)) {
				arr.push( this.createScenerioFromShortcut(mode,modifier,msg, messageContainer) );

				// register a 2nd validation event if present
				if (!isNull(mode2) && !isNull(modifier2) && !isNull(msg2)) {
					arr.push( this.createScenerioFromShortcut(mode2,modifier2,msg2, messageContainer) );
				};

				// and check for a 3rd...
				if (!isNull(mode3) && !isNull(modifier3) && !isNull(msg3)) {
					arr.push( this.createScenerioFromShortcut(mode3,modifier3,msg3, messageContainer) );
				};

			};

			// convert scenerio
			scenerio = arr;

		};

		return scenerio;
	},

	// reform validation arrays - convert from shortcut to full array
	createScenerioFromShortcut : function( mode, modifier, msg, messageContainer )
	{
		return [mode,modifier,msg,messageContainer];
	}

};

// Inherit from CingoKit.Base
setdefault(CingoKit.Form.Element.prototype, CingoKit);