/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       interactive text fields.
 *
 *    @version rev011.2006-10-24
 *    @requires common.js
 *    @requires interactiveTextField.css
 */
/* -------------------------------------------------------------------------- */

var BA_INTERACTIVETEXTFIELD_INSTANCES = [];



/* -------------------- Settings -------------------- */

var BA_INTERACTIVETEXTFIELD_AUTOSETUP_ENABLED = true;
var BA_INTERACTIVETEXTFIELD_CNAMES            = {
	'applied' : 'BAInteractiveTextField',
	'changed' : 'pseudo-changed',
	'hover'   : 'pseudo-hover',
	'focus'   : 'pseudo-focus'
};
var BA_INTERACTIVETEXTFIELD_TYPICAL_HANDLERS  = {
	'focus' : function(node) {
		if (!node.readOnly && !node.disabled) {
			node.appendClassNameBA(BA_INTERACTIVETEXTFIELD_CNAMES.focus);
			this.removeInfoText();
		}
	},
	'blur' : function(node) {
		if (!node.readOnly && !node.disabled) {
			node.removeClassNameBA(BA_INTERACTIVETEXTFIELD_CNAMES.focus);
			this.prepopulateInfoText();
		}
	},
	'mouseover' : function(node) {
		if (!node.readOnly && !node.disabled) {
			node.appendClassNameBA(BA_INTERACTIVETEXTFIELD_CNAMES.hover);
		}
	},
	'mouseout' : function(node) {
		if (!node.readOnly && !node.disabled) {
			node.removeClassNameBA(BA_INTERACTIVETEXTFIELD_CNAMES.hover);
		}
	}
};





/* ------ Constructor : BAInteractiveTextField() ------ */
/**
 * provide interactive text field.
 * @class interactive text field
 * @constructor
 * @param {BAElement} node    text field (input/textarea element) node (required)
 */

function BAInteractiveTextField(node) {
	/** text field (input/textarea element) node
	    @type BAElement @const */
	this.node         = null;
	/** attribute name that stores text for prepopulate
	    @type String @const @private */
	this.searchAttr   = 'title';
	/** flag that the text field is changed or not
	    @type Boolean */
	this.isChanged    = false;
	/** className for status of 'changed'
	    @type String @private @const */
	this.changedCName = BA_INTERACTIVETEXTFIELD_CNAMES.changed;

	if (arguments.length) {
		this.init(node);
	}
}

BAInteractiveTextField.prototype = {
	/**
	 * initialize.
	 * @param {BAElement} node    text field (input/textarea element) node (required)
	 * @private
	 */
	init : function(node) {
		if (!node || !node.nodeType || node.nodeType != 1) {
			throw 'BAInteractiveTextField.init: first argument must be an element node.';
		} else {
			var name = node.nodeName.toLowerCase();
			var type = (name == 'textarea') ? 'textarea' : (name == 'input') ? (node.type || 'text').toLowerCase() : '';
			if (['text', 'textarea'].indexOf(type) == -1) {
				throw 'BAInteractiveTextField.init: specified element node is not allowed.';
			} else if (typeof node.__BAInteractiveTextField_infoTextStore__ == 'string') {
				throw 'BAInteractiveTextField.init: specified element node is already applied.';
			} else {
				this.node = node;
				this.node.appendClassNameBA(BA_INTERACTIVETEXTFIELD_CNAMES.applied);
				this.prepopulateInfoText();
			}
		}
	},

	/**
	 * prepopulate infomation text when text field is 'empty'.
	 */
	prepopulateInfoText : function() {
		// get values.
		var nodeValue   = this.node.value                                    || '';
		var attrValue   = this.node.getAttributeBA(this.searchAttr)          || '';
		var storedValue = this.node.__BAInteractiveTextField_infoTextStore__ || '';

		// prepare node.
		if (typeof this.node.__BAInteractiveTextField_infoTextStore__ != 'string') {
			this.node.__BAInteractiveTextField_infoTextStore__ = attrValue;
			this.node.setAttributeBA(this.searchAttr, '');
		}

		// status check and set text of the field.
		if (nodeValue && nodeValue != attrValue) {
			this.isChanged = true;
		} else {
			this.isChanged = false;
			this.node.value = attrValue || storedValue || '';
		}

		// set className.
		if (this.isChanged) {
			this.node.appendClassNameBA(this.changedCName);
		} else {
			this.node.removeClassNameBA(this.changedCName);
		}
	},

	/**
	 * remove infomation text from text field.
	 * @private
	 */
	removeInfoText : function() {
		if (this.node.value == this.node.__BAInteractiveTextField_infoTextStore__) {
			this.node.value = '';
		}
	}
};



/* -------------------- Function : BAInteractiveTextFieldSetup() -------------------- */
/**
 * Setup BAInteractiveTextField for specitied text field.
 * Call this after page onloaded.
 * @see BAInteractiveTextField
 * @param {BAElement} node        input/textarea element node to setup (required)
 * @param {Object}    handlers    an associative array of 'event type' and 'its event handler function'.
 * @return BAInteractiveTextField instance
 * @type BAInteractiveTextField
 */
function BAInteractiveTextFieldSetup(node, handlers) {
	if (!node || !node.nodeType || node.nodeType != 1) {
		throw 'BAInteractiveTextFieldSetup: first argument must be an element node.';
	} else if (typeof node.__BAInteractiveTextField_instanceID__ != 'number') {
		try {
			var field = new BAInteractiveTextField(node);
		} catch(err) {
			// specitied node was neither <input type="text"> nor <textarea>.
			return null;
		}
		
		var num = BA_INTERACTIVETEXTFIELD_INSTANCES.push(field);
		node.__BAInteractiveTextField_instanceID__ = --num;

		if (typeof handlers != 'object') {
			handlers = BA_INTERACTIVETEXTFIELD_TYPICAL_HANDLERS;
		}
		for (var eventType in handlers) {
			node.addEventListenerBA(eventType, function(e) {
				var _type = e.type;
				var _node = e.currentTarget;
				var _id   = _node.__BAInteractiveTextField_instanceID__;
				handlers[_type].call(BA_INTERACTIVETEXTFIELD_INSTANCES[_id], _node);
			}, this);
		}
		return field;
	}
}



/* -------------------- Function : BAInteractiveTextFieldAutoSetup() -------------------- */
/**
 * Auto setup BAInteractiveTextField for all text fields of whole page.
 * Call this after page onloaded.
 * @see Window#BAInteractiveTextFieldSetup
 */
function BAInteractiveTextFieldAutoSetup() {
	if (BA_INTERACTIVETEXTFIELD_AUTOSETUP_ENABLED) {
		var nodes1 = document.getElementsByTagNameBA('input'   );
		var nodes2 = document.getElementsByTagNameBA('textarea');
		BAConcatNodeList(nodes1, nodes2).forEach(BAInteractiveTextFieldSetup);
	}
}





/* -------------------- Main : register start-up -------------------- */

if (typeof BA == 'object' && BA.ua.DOMok) {
	BAAddOnload(BAInteractiveTextFieldAutoSetup);
}


