
function markSubstring(val, pos, len) {
	var line = '';

	if (pos < 0 || len == 0) {
		line = val;
	}
	else {
		if (pos > 0) {
			line = val.substr(0,pos);
		}
		line += '<u>' + val.substr(pos,len) + '</u>';

		if (pos+len < val.length) {
			line += val.substr(pos+len);
		}
	}
	return line;
}



var widgets = new Array();

var visibleDropDown = '';

function closeDropDowns() {
	/*
	if (!visibleDropDown) return;

	var t;
	if (!e) var e = window.event;
	if (e.target) t = e.target;
	else if (e.srcElement) t = e.srcElement;
	if (t.nodeType == 3)
		t = t.parentNode;
*/
	if (visibleDropDown) {
		widgets[visibleDropDown].showDropDown(false);
		visibleDropDown = false;
	}

}

function Widget() {}

Widget.prototype.register = function() {
	widgets[this.id] = this;
}

Widget.prototype.writeHtml = function() {
	document.write(this.toHtml());
}


function SuggestBox(id) {
	if (arguments.length>0) this.init(id);
}


SuggestBox.prototype = new Widget();

SuggestBox.prototype.init = function(id) {
	this.id = id;
	this.selectedItem = null;
	this.numItems = 0;
	this.values = [];
	this.showAllItems = false;
	this.matchAnywhere = false;
	this.markMatched = true;
	this.allowEmptySearch = false;
	this.observers = [];
	this.dropDownVisible = false;
	this.incUpdates = true;
	this.register();
}

SuggestBox.prototype.setData = function(values) {
	this.values = values;
}

SuggestBox.prototype.getValue = function() {
	return $(this.id).value;
}

SuggestBox.prototype.setValue = function(val,skipNotify) {
	$(this.id).value = val;
	if (!skipNotify) this.notifyObservers(val);
}

SuggestBox.prototype.addObserver = function(o) {
	this.observers[this.observers.length] = o;
}

SuggestBox.prototype.notifyObservers = function(val) {
//alert(this.observers.length);
	for(var i=0;i<this.observers.length;i++) {
		this.observers[i].observedChanged(this,val);
	}
}


SuggestBox.prototype.onkeydown = function(e,event) {

	var k = event.keyCode;
//alert("got key "+k+" elem="+e.id+" selected="+(this.selectedItem?this.selectedItem.id:'none'));
//alert(this.onkeydown.toString());
// Activate the selection
	if (k==13) {
		this.itemClicked();
		return false;
	}

	if (k==9) {
		closeDropDowns();
		return true;
	}

// Check for up and down keys
//	return document.all ? this.handleScrollingKeys(k):true;
	return this.handleScrollingKeys(k);
}

SuggestBox.prototype.onkeypress = function(e,event) {
	var k = event.keyCode;

	if (k==13) return false;

// Check for up and down keys

	if (this.incUpdates) {
		this.notifyObservers(this.getValue());
	}
	return true;
}

SuggestBox.prototype.handleScrollingKeys = function(k) {

	if (k!=38 && k!=40) return true;

	var newItemId = '';

	if (this.selectedItem) {
		var nns = new Array();
		nns = this.selectedItem.id.split('-');

		var idx = 1* nns[2];

	// Move selection up
		if (k==38) {
			idx = (idx > 0) ? idx-1 : this.numItems-1;
		}
	// Move selection down
		else if (k==40) {
			idx = (idx < this.numItems-1) ? idx+1 : 0;
		}

		newItemId = nns[0] + '-' +nns[1] + '-' + idx;
	}
	else {
		newItemId = this.id + '-item-0';
	}

	this.keyItemOver(newItemId);

	return false;
}

SuggestBox.prototype.keyItemOver = function(itemId) {
	var item = $(itemId);
	if (item) {
		if (item.scrollIntoView) {
			item.scrollIntoView(false);
		}
		this.itemOver(item);
	}
}

SuggestBox.prototype.onkeyup = function (e, event) {

// Do not change the list on cursor keys
	var k = event.keyCode;
//alert("keyup "+k);
	if (k==38 || k==40) return true;
	if (k==13) return false;

// Change the list
	var str = e.value;
	this.populateDropDown(str);

	return true;
}

SuggestBox.prototype.onfocus = function(e) {
// Change the list
//	var str = e.value;
//	this.populateDropDown(str);
}

SuggestBox.prototype.onblur = function(e) {
//	this.showDropDown(false);
}

SuggestBox.prototype.onmousedown = function(e, event) {

	if (!this.dropDownVisible) {
	// Close previous dropdowns
		closeDropDowns();
	// Change the list
		var str = e.value;
		this.populateDropDown(str);
	}
	else {
		this.showDropDown(false);
	}
	return true;
}

SuggestBox.prototype.onmouseup = function(e, event) {
	return true;
}


SuggestBox.prototype.itemOver = function(e) {
	if (this.selectedItem) {
		this.selectedItem.className = 'suggest-item';
	}

	this.selectedItem = e;

	if (this.selectedItem) {
		this.selectedItem.className = 'suggest-item suggest-item-selected';
	}
}

SuggestBox.prototype.itemClicked = function() {
	if (this.selectedItem) {

	// Selected value
		var val = this.selectedItem.title;

	// Set its value to the selected suggest item
		this.setValue(val);

	// Give the focus to the textfield
		//e.focus();

	// Change the dropdown list;
		if (this.showAllItems) {
			this.showDropDown(false);
		}
		else {
			this.populateDropDown(this.getValue());
		}
	}
}

SuggestBox.prototype.showAll = function() {
	var old = this.showAllItems;
	this.showAllItems = true;
	this.populateDropDown('');
	this.showAllItems = old;
}

SuggestBox.prototype.showDropDown = function(visible) {
	var e = $(this.id + '-dropdown');
	e.style.display = visible ? '':'none';
	this.dropDownVisible = visible;
	visibleDropDown = this.id;
}

SuggestBox.prototype.populateDropDown = function(str) {

	var nn = this.id;

	str = str.toLowerCase();

	var e = $(nn + '-dropdown');

	var fullMatch = false;

	var pelem = "widgets['" + nn + "']";

	var html = '';

	for(var i=0, counter=0;i<this.values.length && (str.length || this.allowEmptySearch || this.showAllItems);i++) {
		var val = this.values[i];

		var lval = val.toLowerCase();

		var pos = lval.indexOf(str);

		if (this.showAllItems || pos==0 || (pos>0 && this.matchAnywhere) ) {
			if (pos == 0 && (lval.length == str.length || lval.indexOf(' - ') == str.length )) {
				fullMatch = true;
			}

			var line = '';

			if (pos < 0 || !this.markMatched) {
				line = val;
			}
			else {
				line = markSubstring(val,pos,str.length);
			}

			html += this.makeItemHtml(nn + '-item-' + counter, val, line, pelem);
			counter ++;
		}
	}

	if (str.length>0 && counter<=1 && fullMatch && !this.showAllItems) {
		html = '';
		counter = 0;
	}
	this.numItems = counter;
//alert('html='+html);
	e.innerHTML = html;

	this.showDropDown(html?true:false);

// Select the first item
	if (html) {
		this.keyItemOver(nn+'-item-0');
	}
	else {
		this.selectedItem = null;
	}
}

SuggestBox.prototype.makeItemHtml = function(id,val,line,pelem) {
	return '<div class="suggest-item" id="' + id + '" ' + 
		'title="' + val + '" ' + 
		'onmouseover="' + pelem + '.itemOver(this)" ' +
		'onmouseout="' + pelem + '.itemOver(null)" ' +
		'onmousedown="' + pelem + '.itemClicked()">' + line + '</div>';
}


SuggestBox.prototype.inputTextToHtml = function() {
	var s = '';
	s += '<input class="suggest-input" type="text" id="' + this.id + '" ';
	s += 'name="' + this.id+ '"autocomplete="off" ';
	s += 'onkeydown="return widgets[this.id].onkeydown(this,event)" ';
	s += 'onkeypress="return widgets[this.id].onkeypress(this,event)" ';
	s += 'onkeyup="return widgets[this.id].onkeyup(this,event)" ';
	s += 'onmousedown="return widgets[this.id].onmousedown(this,event);" ';
	s += 'onmouseup="return widgets[this.id].onmouseup(this,event);" ';
	s += 'onfocus="widgets[this.id].onfocus(this)" onblur="widgets[this.id].onblur(this)"';
	s += '>';
	return s;
}

SuggestBox.prototype.inputImageToHtml = function(imgsrc) {
	var s = '';
	s += '<input class="suggest-input-image" type="image" autocomplete="off" id="' + this.id + '" ';
	s += 'name="' + this.id+ '" src="' + imgsrc + '"';
//	s += 'onclick="this.focus()" ';
	s += 'onkeydown="return widgets[this.id].onkeydown(this,event)" ';
	s += 'onkeypress="return widgets[this.id].onkeypress(this,event)" ';
//	s += 'onkeypress="return event.keyCode!=13" ';
	s += 'onkeyup="return widgets[this.id].onkeyup(this,event)" ';
	s += 'onmousedown="this.focus(); return widgets[this.id].onmousedown(this,event)" ';
//	s += 'onfocus="widgets[this.id].onfocus(this)" onblur="widgets[this.id].onblur(this)"';
	s += '>';
	return s;
}

SuggestBox.prototype.dropDownToHtml = function() {
	var pelem = "widgets['"+this.id+"']";
	var s = '<div class="suggest-dropdown" id="' + this.id + '-dropdown" ' + 
		'onmousedown="event.cancelBubble=true; return false" style="display: none"></div>';
	return s;
}


SuggestBox.prototype.toHtml = function() {
	return this.inputTextToHtml() + this.dropDownToHtml();
}




