/**
 * MultiBox Widget
 * 
 * This widget converts a textbox input into a multi input text box.
 * By setting AutoComplete = true and proper variables this widget can
 * make HTTPRequest calls to the requested ajax controller and updating 
 * auto-completion and suggession boxes as necessary.
 *
 * Javascript 1.1
 * 
 * LICENSE: This source file is property of the State of California.
 *
 * @package    OES_CMS
 * @author     Eihab Ibrahim <eihab@mindsetsoft.com>
 * @copyright  2005 Mindset Software Inc.
 * @license    doc/license.txt
 * @version    SVN: $Id: autocomplete.js 1887 2006-08-15 22:03:36Z eihab $
 * @since      File available since Release 1.0
 */

MultiBox.prototype.init             = init;
MultiBox.prototype.autoComplete     = autoComplete;
MultiBox.prototype.completeResponse = completeResponse;
MultiBox.prototype.suggestResponse  = suggestResponse;
MultiBox.prototype.setBoxText       = setBoxText;
MultiBox.prototype.sendRequest      = sendRequest;
MultiBox.prototype.addItem          = addItem;
MultiBox.prototype.removeItem       = removeItem;
MultiBox.prototype.updateItemView   = updateItemView;
MultiBox.prototype.appendFormInputs = appendFormInputs;
MultiBox.prototype.associateInputs  = associateInputs;
MultiBox.prototype.showLookupDiv    = showLookupDiv;
MultiBox.prototype.onChange         = onChange;

function MultiBox(instanceName) {

/**
 * The name of this instance (passed through constructor)
 * 
 * @var string
 * @access public
 */
var name;
this.name = instanceName;

/**
 * Text box (to AutoComplete) ID
 * 
 * @var string
 * @access public
 */
var textBox;

/**
 * Auto-Completion div ID
 * 
 * @var string
 * @access public
 */
var completeDiv;

/**
 * Suggesstion div ID
 * 
 * @var string
 * @access public
 */
var suggestDiv;

/**
 * Get HTML instead of JSON
 * 
 * @var bool
 * @access public
 */
var getHTML;

/**
 * Request URI
 * 
 * @var string
 * @access public
 */
var reqURI;

/**
 * Get substring suggestions automatically
 * 
 * @var string
 * @access public
 */
var autoSuggest;

/**
 * Holds last keyed value
 * 
 * @var string
 * @access public
 */
var lastKeyed;
this.lastKeyed = '';

/**
 * Extra parameters for the AJAX call
 * 
 * @var string
 * @access public
 */
var extraParams;

/**
 * Allow multiple items to be added (separated by obj.separator)
 * (Default to true)
 *
 * @var bool
 * @access public
 */
var multiple;
this.multiple = true;

/**
 * Separator to add between selected items
 * (Default comma ',')
 * Add space if required
 *
 * @var bool
 * @access public
 */
var separator;
this.separator = ', ';

/**
 * Update timeout object (used internally for avoiding type ahead jitter)
 *
 * @var bool
 * @access private
 */
var timeOut;
this.timeOut = '';

/**
 * Ajax (?) view, converts text box to a box with drop down menu of current items.
 * (Requires Mootools)
 *
 * @var bool
 * @access public
 */
var ajaxView;
this.ajaxView = true;

var listDivId;
this.listDivId = false;

var listDivContent;
this.listDivContent = false;

var containerClass;
this.containerClass = 'acContainer';

var listDivClass;
this.listDivClass = 'acListDiv';

var textBoxClass;
this.textBoxClass = 'acBox';

var slider;

var autoCompleter;
this.autoCompleter = false;

var collection;
this.collection = new Array();

var trigger; 
this.trigger = false; 

var affectedArea; 
this.affectedArea = false; 

var lookupDiv;
this.lookupDiv = false;

/**
 * Enable adding arbitrary data using enter
 *
 * @var bool
 * @access public
 */
var protected;
this.protected = false;

var getID;
this.getID = false;

var nElements;
this.nElements = new Array(); 

var noSlide;
this.noSilde = false;

var form;
this.form = false;

var relatedObject;
this.relatedObject = false;

var limit;
this.limit = false;

var allowDuplicate;
this.allowDuplicate = false;
}

function init() {
	YAHOO.util.Event.addListener(this.textBox, "keyup", function(e, obj){obj.autoComplete(e);}, this);
	
	// Ajax view Setup
	if (this.ajaxView) {
		// Setup view area
		textBox = document.getElementById(this.textBox);

		// Add input save event listener
		this.appendFormInputs();
		
		if (!this.listDivId) {
			this.listDivId = this.name + 'listDiv';
			var tdiv = document.createElement('div');
			tdiv.id = this.listDivId;
			tdiv.className = this.listDivClass;
		} else {
			tdiv = document.getElementById(this.listDivId);
			tdiv.className = this.listDivClass;
		}

		this.listDivContent = this.name + 'listDivContent';
		var cul = document.createElement('ul');
		cul.id = this.listDivContent;
		tdiv.appendChild(cul);
		if (!tdiv.parentNode) {
			textBox.parentNode.appendChild(tdiv);
		}
		
		if (!this.noSlide) {
			this.affectedArea = ((this.affectedArea)?this.affectedArea:tdiv.id);

 
			//this.slider = new Fx.Slide(this.affectedArea, {duration: 100});
			//this.slider.hide();

		}
		
		this.trigger = (this.trigger)?this.trigger:textBox.id;
		YAHOO.util.Event.addListener(this.trigger, "click", function(e, obj){ 
			if(obj.slider.wrapper["offset" + obj.slider.layout.capitalize()] == 0){
				obj.slider.toggle();
				// Disable enter key for now
				document.onkeypress = function(e){
					var keycode = e ? e.which : window.event.keyCode;
					return (keycode != 13);
				}
			}
		}, this);
		
		// Attach affected area toggle slide effect
		if (!this.noSlide) {
			YAHOO.util.Event.addListener(document.body, "click", function(e, obj){
	
				if(obj.slider.wrapper["offset" + obj.slider.layout.capitalize()] > 0){
					var t = e.target;
					var found = false;
					while(t) {
						if(t == document.getElementById(obj.trigger) 
						|| t == document.getElementById(obj.lookupDiv) 
						|| t == document.getElementById(obj.affectedArea) 
						|| t == document.getElementById(obj.listDivId) 
						|| t == document.getElementById(obj.slider) 
						|| t == document.getElementById(obj.textBox)
						|| t == document.getElementById(obj.completeDiv)
						|| t == document.getElementById(obj.suggestDiv)) {
							found = true;
							break;
						} else {
							if (this.nElements) {
								for (var i=0; i<this.nElements.length; i++) {
									if (t == document.getElementById(this.nElements[i])) {
										found = true;
										break;
									}
								}
							}
							if (!found) {
								t = t.parentNode;
							}
						}					
					}
					if (!found) {
						obj.slider.toggle();
						// Enable enter key once we're hidden
						if (e.target.id && YAHOO.util.Event.getListeners) {
							// Make sure we're not enabling enter key when we're moving to another widget
							var listeners = YAHOO.util.Event.getListeners(document.getElementById(e.target.id), "focus");
							if (listeners && listeners.length > 0 && e.target.id.indexOf('Box')) {
								return;
							}
						}
						document.onkeypress = '';
					}
				}
			}, this);
		}
		if (this.lookupDiv) {
			// Hide initially
			document.getElementById(this.lookupDiv).style.display = 'none';
			
			// Position underneath the textbox
			document.getElementById(this.lookupDiv).style.position = 'absolute';
			// Add event listener
			YAHOO.util.Event.addListener(document.body, "click", function(e, obj){
					var t = e.target;
					var found = false;
					while(t.parentNode) {
						 if(t == document.getElementById(obj.textBox) 
						 || t == document.getElementById(obj.lookupDiv)) {
							found = true;
							break;
						} else {
							t = t.parentNode;
						}					
					}
					if (!found) {
						document.getElementById(obj.lookupDiv).style.display = 'none';
					}
			}, this);
		}
	
		// Alter textbox and container
		YAHOO.util.Dom.addClass(textBox.parentNode, this.containerClass);
		YAHOO.util.Dom.addClass(textBox, this.textBoxClass);
		
		// Load input data (if any)
		var dataDiv = document.getElementById(this.name+'Data');
		var inputsToLoad = new Array();
		for (i=0; i<dataDiv.childNodes.length; i++) {
			if (dataDiv.childNodes[i].name && dataDiv.childNodes[i].name.indexOf(this.name+'data') > -1) {
				inputsToLoad.push(dataDiv.childNodes[i].value);
			}
		}
		dataDiv.innerHTML = '';
		for (j=0; j<inputsToLoad.length; j++) {
			if (inputsToLoad[j]) {
				var obj = eval(inputsToLoad[j]);
				this.addItem(obj.title, obj.id);
			}
		}
	} else if (this.lookupDiv) {
		// Hide initially
		document.getElementById(this.lookupDiv).style.display = 'none';
		
		// Position underneath the textbox
		document.getElementById(this.lookupDiv).style.position = 'absolute';
		// Add event listener
		YAHOO.util.Event.addListener(document.body, "click", function(e, obj){
				var t = e.target;
				var found = false;
				while(t.parentNode) {
					 if(t == document.getElementById(obj.textBox) 
					 || t == document.getElementById(obj.lookupDiv)) {
						found = true;
						break;
					} else {
						t = t.parentNode;
					}					
				}
				if (!found) {
					document.getElementById(obj.lookupDiv).style.display = 'none';
				}
		}, this);
	}
}

function appendFormInputs() {
	var form = document.getElementById(this.textBox).form;
	this.form = form;
	if (form) {
		YAHOO.util.Event.addListener(form, "submit", function(e, obj){obj.associateInputs();}, this);
	}
}

function associateInputs() {
	var form = this.form;
	var dataDiv = document.getElementById(this.name+'Data');
	var inputsToMove = new Array();
	for (i=0; i<dataDiv.childNodes.length; i++) {
		if (dataDiv.childNodes[i].name.indexOf(this.name+'data') > -1) {
			inputsToMove.push(dataDiv.childNodes[i]);
		}
	}
	
	var input = document.createElement('input');
	input.setAttribute('name', (this.name + 'dataSize'));
	input.setAttribute('type', 'hidden');
	input.setAttribute('value', inputsToMove.length);
	form.appendChild(input);
	
	for (i=0; i<inputsToMove.length; i++){
		form.appendChild(inputsToMove[i]);
	}
}

function showLookupDiv() {
	var lookupDiv = document.getElementById(this.lookupDiv);
	lookupDiv.style.display='';
	var parent = document.getElementById(this.textBox).parentNode;
	for (i=0; i<parent.childNodes.length; i++) {
		if (parent.childNodes[i] == document.getElementById(this.textBox)) {
			if (i < parent.childNodes.length-1) {
				parent.insertBefore(lookupDiv, parent.childNodes[i+1]);
			} else {
				parent.appendChild(lookupDiv);
			}
			break;
		}
	}
}

function autoComplete(e) {
	var keycode;
	// Display suggest/complete box if requested
	if (this.lookupDiv && this.autoCompleter) {
		if (document.getElementById(this.textBox).value.length > 0) {
			this.showLookupDiv();
		} else {
			document.getElementById(this.lookupDiv).style.display='none';
		}
	}
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;
	if (keycode==13) {
		if (!this.protected && this.ajaxView)
			this.addItem();
	} else if (keycode) {
		if (!this.autoCompleter)
			return;
		objInstance = this;
		if (this.timeOut) {
			clearTimeout(this.timeOut);
		}
		var obj = this;
		this.timeOut = setTimeout(function(){obj.sendRequest();}, 750);
	}
}

function addItem(item, id) {
  


	if (!item) {
		item = document.getElementById(this.textBox).value;
	}
	if (this.limit && this.collection.length >= this.limit) {
		return false;
	}
	// Check for duplicates
	if (!this.allowDuplicate) {
		for (var i=0; i<this.collection.length; i++) {
			if (this.collection[i].id == id) {
				return false;
			}
		}
	}
	data = new dataItem();
	data.title = item;
	data.id = id;
	document.getElementById(this.textBox).value = '';
	document.getElementById(this.textBox).focus();
	if (item.length > 0) {
		this.collection.push(data);
		this.updateItemView();
		this.onChange();
	}
}

function removeItem(item) {
	this.collection.splice(item, 1);
	this.updateItemView();
	this.onChange();
}

function updateItemView() {
	var j=0;
	var ul = document.getElementById(this.listDivContent);
	var dataDiv = document.getElementById(this.name+'Data');
	ul.innerHTML = '';
	dataDiv.innerHTML = '';
	if (this.collection.length > 0) {
		for (i=this.collection.length-1; i>=0; i--) {
			var li = document.createElement('li');
			li.innerHTML = this.collection[i].title;
			var ahref = '&nbsp;<a href="javascript:void(0)" onclick="javascript:'+this.name+'.removeItem('+i+')"><img src="/assets/images/icons/tag-delete.png" height="12" width="12" title="Remove"></a>';
			li.innerHTML += ahref;
			/* This is the clean way to do it. damn OO js..
			var a = document.createElement('a');
			a.href = 'javascript:void(0)';
			a.innerHTML = '(remove)';
			YAHOO.util.Event.addListener(a, "click", function(e, obj){obj.removeItem();}, this);
			li.appendChild(a);
			*/
			// Add hidden input
			var input = document.createElement('input');
			input.setAttribute('name', (this.name + 'data' + i));
			input.setAttribute('type', 'hidden');

			var jsonString = '{"title":"'+this.collection[i].title+'", "id":"'+((this.collection[i].id)?this.collection[i].id:'')+'"}';
			input.setAttribute('value', jsonString);
			dataDiv.appendChild(input);
			ul.appendChild(li);
		}
	}
}

function sendRequest() {

  
    if( !ContentManager )
        ContentManager = new ContentBoxManager();

    if( ContentManager )
        ContentManager.displayAutoComplete();

	// Get the string to auto-complete
	reqString = document.getElementById(this.textBox).value;

	// Return if box is empty
	if (reqString.length == 0) {
		this.lastKeyed = '';
		this.completeResponse(0);
		this.suggestResponse(0);
		return;
	}
	
	// Avoid sending request when nothing changed
	if (reqString == this.lastKeyed) {
		return;
	} else {
		// Otherwise create a request
		if (reqString.indexOf(this.separator)!=-1) {
			// Multiple words, get last comma seperated word
			reqString = reqString.substring((reqString.lastIndexOf(this.separator)+2));
		} else {
			this.lastKeyed = reqString;
		}
	}
	
	// Set up call parameters
	param  = 'name='+reqString;
	param += '&object='+this.name;

	if (this.getHTML) {
		param += '&'+'type=html';
	}

	if (this.extraParams!=null && this.extraParams.length > 0) {
		param += this.extraParams;
	}
	
	if (this.relatedObject) {
		param += '&relatedObject='+this.relatedObject;
	}
	
	var _this = this;
	
	var uri = this.reqURI + '?' + param;
	var callbackFun = 
		{ 
			success: function(o) { _this.completeResponse(o)}, 
			failure: function(o) { _this.completeResponse(o)}
		}; 
	
	var request = YAHOO.util.Connect.asyncRequest('GET', uri, callbackFun);		
	
	if (this.autoSuggest) {
		param += '&mode=substr';
		uri = this.reqURI + '?' + param;

		var callbackFun = 
		{
			success: function(o) { _this.suggestResponse(o)}, 
			failure: function(o) { _this.suggestResponse(o)}
		};
		var request = YAHOO.util.Connect.asyncRequest('GET', uri, callbackFun);		
	}
}

function completeResponse(data) {
	var html = data.responseText;

	var compDiv = document.getElementById(this.completeDiv);

	if (html != null && html != 0) {
		compDiv.innerHTML = html;
	} else {
		compDiv.innerHTML = 'No matches found';
	}
}

function suggestResponse(data) {
	var html = data.responseText;

	var sugDiv = document.getElementById(this.suggestDiv);

	if (html != null && html != 0) {
		sugDiv.innerHTML = html;
	} else {
		sugDiv.innerHTML = 'No suggesstions';
	}
}

function setBoxText (text, id){
	if (this.ajaxView) {
		this.addItem(text, id);
		return;
	}
	var box = document.getElementById(this.textBox);
	if (this.multiple) {
		var reqString = box.value;

		if (reqString.indexOf(this.separator)!=-1) {
			// Multiple subjects, get last comma seperated subject
			var ex = reqString.substring(0,(reqString.lastIndexOf(this.separator)));
			box.value = ex + this.separator + text + this.separator;
		} else {
			box.value = text + this.separator;
		}
	} else {
		box.value = text;
	}
	box.focus();
}

function dataItem() {
	var id;
	var title;
}

function onChange() {}
