// The global array of objects that have been instanciated
if (!Bs_Objects) {var Bs_Objects = [];};



/**
* Extended Text Field.
* see http://www.blueshoes.org/en/javascript/extendedtextfield/
* 
* dependencies: 
*   <script type="text/javascript" src='/_bsJavascript/core/lang/Bs_Misc.lib.js'></script>
*   <script type="text/javascript" src='/_bsJavascript/core/html/Bs_HtmlUtil.lib.js'></script>
*   <script type="text/javascript" src='/_bsJavascript/core/form/Bs_FormUtil.lib.js'></script>
* 
* @author     andrej arn <andrej-at-blueshoes-dot-org>
* @package    javascript_components
* @subpackage extendedtextfield
* @copyright  blueshoes.org
* @since      bs-4.6
* @status     experimental
*/
function Bs_ExtendedTextField() {
	
	
	/**
  * Unique Object/Tag ID is initialized in the constuctor.
  * Based on this._id. Can be used in genarated JS-code as ID. Is set together 
  * from the  classname + this._id (see _constructor() code ).
  *
  * @access private
  * @var  string 
  */
  this._objectId;
	
	/**
	* @access ?
	* @var    string string
	*/
	this.string;
	
	/**
	* @access ?
	* @var    ? values
	*/
	this.values;
	
	/**
	* @access ?
	* @var    bool byString
	*/
	this.byString = false;
	
	/**
	* the name of the input field.
	* @access ?
	* @var    string inputFieldName
	*/
	this.inputFieldName;
	
	/**
	* the id of the input field.
	* @access ?
	* @var    string inputFieldId
	*/
	this.inputFieldId;
	
	/**
	* fullpath to the arrow icon.
	* @access public
	* @var    string arrowIcon
	*/
	this.arrowIcon = '/_bsJavascript/components/extendedtextfield/img/dropdownArrow.gif';
	
	/**
	* if the form should be submitted if enter is pressed.
	* is only used together with renderReplace().
	* @access public
	* @var    bool submitOnEnter (default is false)
	*/
	this.submitOnEnter = false;
	
	/**
	* the form object of the original form field. used with renderReplace().
	* needed for the submitOnEnter feature.
	* @access public
	* @var    elm _formElm (form element)
	*/
	this._formElm;
	
	
	this._containerDiv;
	
	
	/**
	* constructor.
	*/
	this._constructor = function() {
    this._id = Bs_Objects.length;
    Bs_Objects[this._id] = this; 
    this._objectId = "Bs_Etf_"+this._id;
	}
	
	
	/*
	this.initByArray = function(values) {
		this.inputFieldName = 'bs_etf_hiddenField';
		this.inputFieldId   = 'bs_etf_hiddenField';
		
		this.values = values;
	}*/
	
	
	this.initByString = function(string, array) {
		this.inputFieldName = this._objectId + '_hiddenField';
		this.inputFieldId   = this._objectId + '_hiddenField';
		
		this.byString = true;
		this.string   = string;
		this.values   = array;
	}
	
	/**
	* inits the field. reads its current value and assigns the alternatives passed in the 
	* 2nd param to the words.
	* @access public
	* @param  string fieldId
	* @param  array array (alternatives, a hash, see the examples)
	* @return void
	*/
	this.initByField = function(fieldId, array) {
		var inputFieldObj   = document.getElementById(fieldId);
		this.inputFieldName = inputFieldObj.name;
		this.inputFieldId   = fieldId;
		
		this.byString = true;
		this.string   = inputFieldObj.value
		this.values   = array;
	}
	
	
	/**
	* @access public
	* @param  string tagId
	* @return bool
	*/
	this.renderInto = function(tagId) {
		var out = this.render();
		document.getElementById(tagId).innerHTML = out;
		this._containerDiv = document.getElementById(this._objectId + '_div');
		return true;
	}
	
	
	/**
	* only works with internet explorer.
	* @access public
	* @param  string tagId
	* @return bool
	*/
	this.renderReplace = function(tagId) {
		if (!ie) return false;
		
		if (this.submitOnEnter) {
			if (typeof(bsFormGetFormForField) == 'undefined') {
				alert("Webmaster: for the submitOnEnter you need to include the file /core/form/Bs_FormUtil.lib.js.");
			} else {
				this._formElm = bsFormGetFormForField();
			}
		}
		
		var out = this.render();
		var prevElm = document.getElementById(tagId);
		var width  = prevElm.offsetWidth;
		var height = prevElm.offsetHeight;
		prevElm.outerHTML = out;
		this._containerDiv = document.getElementById(this._objectId + '_div');
		this._containerDiv.style.width  = width;
		this._containerDiv.style.height = height;
		return true;
	}
	
	
	/**
	* renders the html of the component.
	* @access public (mostly used internally)
	* @return string
	*/
	this.render = function() {
		var out = '';
		
		//var valueArr = this.values.split(' ');
		//for (var i=0; i<this.values.length; i++) {
		
		var outWordsHtml = new Array;
		var outWords     = new Array;
		
		if (this.byString) {
			var outString = this.string;
		}
		
		var i = 0;
		for (var word in this.values) {
			outWords[outWords.length] = word;
			var outWordStr = '';
			if (this.values[word].length > 0) {
				outWordStr += '<span id="'+this._objectId+'_spanWord_' + i + '">' + word + '</span>';
				outWordStr += '<span onclick="Bs_Objects['+this._id+'].toggleSelect(\'' + i + '\');" contentEditable="false" style="vertical-align: middle;"><img src="' + this.arrowIcon + '" border="0" align="middle" alt=""></span> ';
				if (this.byString) {
					//replace words with words-including-dropdown, but only for full words, 
					//example: don't replace the 'foo' in 'foobar'.
					do {
						var pos = outString.search(word); //, outWordStr
						if (pos == -1) break;
						
						//check left
						if (pos > 0) {
							var charCode = outString.charCodeAt(pos -1)
							if ((charCode >= 97) && (charCode <= 122)) break; //a-z
							if ((charCode >= 65) && (charCode <= 90))  break; //A-Z
							if ((charCode >= 48) && (charCode <= 57))  break; //0-9
						}
						
						//check right
						if (pos < outString.length - word.length) {
							var charCode = outString.charCodeAt(pos + word.length)
							if ((charCode >= 97) && (charCode <= 122)) break; //a-z
							if ((charCode >= 65) && (charCode <= 90))  break; //A-Z
							if ((charCode >= 48) && (charCode <= 57))  break; //0-9
						}
						
						//outString = outString.replace(word, outWordStr);
						outString = outString.substr(0, pos) + outWordStr + outString.substr(pos + word.length);
						break;
					} while (true);
				}
				
				var layer = '';
				layer += '<div id="'+this._objectId+'_divWord_' + i + '" style="display:none; position:absolute; border:1px solid black; background-color:white; cursor:hand; cursor:pointer; padding:0px;" onclick="Bs_Objects['+this._id+'].chooseWord(\'' + i + '\');">';
				layer += '<div id="'+this._objectId+'_divWord_' + i + '_0" style="padding-left:3px; padding-right:3px; padding-top:1px; padding-bottom:1px;" onmouseover="Bs_Objects['+this._id+'].optionWordMouseOver('+i+', 0);" onmouseout="Bs_Objects['+this._id+'].optionWordMouseOut('+i+', 0);">' + word + '</div>';
				for (var j=1; j<=this.values[word].length; j++) {
					if (word == this.values[word][j -1]) continue; //already had that word
					layer += '<div id="'+this._objectId+'_divWord_' + i + '_' + j + '" style="position:relative; padding-left:3px; padding-right:3px; padding-top:1px; padding-bottom:1px;" onmouseover="Bs_Objects['+this._id+'].optionWordMouseOver('+i+', '+j+');" onmouseout="Bs_Objects['+this._id+'].optionWordMouseOut('+i+', '+j+');">' + this.values[word][j -1] + '</div>';
				}
				layer += '</div>';
				var body = document.getElementsByTagName('body').item(0);
				body.insertAdjacentHTML('beforeEnd', layer);
				
			} else {
				outWordStr += word;
			}
			
			outWordsHtml[outWordsHtml.length] = outWordStr;
			i++;
		}
		
		out += outWordsHtml.join(' ');
		
		
		var endOut = '';
		endOut += '<div id="'+this._objectId+'_div" style="border:1px solid black; background-color:white;" contentEditable="true" onblur="Bs_Objects['+this._id+'].updateHiddenField();" onkeydown="return Bs_Objects['+this._id+'].typing();">';
		
		if (this.byString) {
			endOut += outString;
		} else {
			endOut += out;
		}
		
		endOut += '</div>';
		endOut += '<input type="hidden" name="' + this.inputFieldName + '" id="' + this.inputFieldId + '" size="50" value="';
		if (this.byString) {
			endOut += bs_filterForHtml(this.string);
		} else {
			endOut += outWords.join(' ');
		}
		endOut += '">';
		
		return endOut;
	}
	
	
	this.updateHiddenField = function() {
		document.getElementById(this.inputFieldId).value = this._containerDiv.innerText;
	}
	
	
	this.toggleSelect = function(id) {
		var divId      = this._objectId+'_divWord_' + id;
		var wordSpanId = this._objectId + '_spanWord_' + id;
		var myDiv = document.getElementById(divId);
		if (myDiv.style.display == 'none') {
			myDiv.style.display = 'block';
			var wordSpanTag = document.getElementById(wordSpanId);
			var pos = getAbsolutePos(wordSpanTag, false);
			myDiv.style.top     = pos.y + wordSpanTag.offsetHeight;
			myDiv.style.left    = pos.x;
		} else {
			myDiv.style.display = 'none';
		}
	}
	
	this.chooseWord = function(id) {
		divId  = this._objectId+'_divWord_'  + id;
		spanId = this._objectId + '_spanWord_' + id;
		var replaceWith = window.event.srcElement.innerText;
		document.getElementById(spanId).innerText    = replaceWith;
		document.getElementById(divId).style.display = 'none';
		
		this.updateHiddenField();
	}
	
	this.optionWordMouseOver = function(i, j) {
		divId = this._objectId+'_divWord_' + i + '_' + j;
		var divElm = document.getElementById(divId);
		divElm.style.backgroundColor = '#08246B';
		divElm.style.color = 'white';
	}
	this.optionWordMouseOut = function(i, j) {
		divId = this._objectId+'_divWord_' + i + '_' + j;
		var divElm = document.getElementById(divId);
		divElm.style.backgroundColor = 'white';
		divElm.style.color = 'black';
	}
	
	this.typing = function() {
		switch (window.event.keyCode) {
			case 13: //enter
				if (this.submitOnEnter && this._formElm) {
					try {
						this._formElm.submit();
					} catch (e) {
						alert("Webmaster: could not submit the form. Do you by accident have a submit button named 'submit'?");
					}
				}
				return false;
			default:
		}
		return true;
	}
	
	
	
	this._constructor(); //call the constructor. needs to be at the end.
	
	
}


