﻿Type.registerNamespace("Nws.UI");

Nws.UI.FilterableListBox = function(element) {
	Nws.UI.FilterableListBox.initializeBase(this, [element]);
	
	this._delayInterval = 200;
	this._delayTimeout = null;
	this._elementChangeDelegate = Function.createDelegate(this, this._elementChange);
	this._elementClickDelegate = Function.createDelegate(this, this._elementClick);
	this._filterTextBox = null;
	this._filterTextBoxKeyupDelegate = Function.createDelegate(this, this._filterTextBoxKeyup);
	this._filterTextCache = null;
	this._items = null;
	this._itemsCache = null;
	this._postBackMode = 0;
	this._valueInternal = null;
}
Nws.UI.FilterableListBox.prototype = {
	add_filtered : function(handler) {
		this.get_events().addHandler("filtered", handler);
	},
	remove_filtered : function(handler) {
		this.get_events().removeHandler("filtered", handler);
	},
	add_filtering : function(handler) {
		this.get_events().addHandler("filtering", handler);
	},
	remove_filtering : function(handler) {
		this.get_events().removeHandler("filtering", handler);
	},

	get_delayInterval : function() {
		return this._delayInterval;
	},
	set_delayInterval : function(value) {
		this._delayInterval = value;
	},
	get_filterTextBox : function() {
		return this._filterTextBox;
	},
	set_filterTextBox : function(value) {
		if(this.get_isInitialized())
			throw Error.invalidOperation("filterTextBox can only be set before initialization.");
		this._filterTextBox = value;
	},
	get_items : function() {
		return this._items;
	},
	set_items : function(value) {
		if(this.get_isInitialized())
			throw Error.invalidOperation("items can only be set before initialization.");
		this._items = value;
	},
	get_postBackMode : function() {
		return this._postBackMode;
	},
	set_postBackMode : function(value) {
		if(this._postBackMode != value) {
			var initialized = this.get_isInitialized();
			if(initialized)
				this._unwirePostBackEvent();
			this._postBackMode = value;
			if(initialized)
				this._wirePostBackEvent();
		}
	},

	_elementChange : function() {
		this.doPostBack(null);
	},
	_elementClick : function() {
		this.doPostBack("click");
	},
	_filterCallback : function() {
		this._filterInternal(this._valueInternal);
	},
	_filterInternal : function(value) {
		var expression = this._getFilterExpression(value);
		var items = this.get_items();
		if((value.length > 0) && (this._filterTextCache == value.substring(0, value.length -1)))
			items = this._itemsCache;
		this._itemsCache = [];
		var element = this.get_element();
		element.options.length = 0;
		var index = 0;
		for(var i = 0;i < items.length;i++) {
			var item = items[i];
			if(expression.test(this._getMatchText(item)) && item.enabled) {
				this._itemsCache[index] = item
				element.options[index++] = new Option(item.text, item.value, false);
			}
		}
		this._filterTextCache = value;
		this.raiseFiltered(Sys.EventArgs.Empty);
	},
	_filterTextBoxKeyup : function(event) {
		this.filter(this._filterTextBox.value);
	},
	_getFilterExpression : function(value) {
		var expression = "";
		var values = value.trim().split(" ");
		for(var i = 0;i < values.length;i++) {
			if(i == values.length - 1) {
				expression += ".*" + values[i];
				break;
			}
			expression += "(?=.*" + values[i] + ")";
		}
		return new RegExp(expression, "i");
	},
	_getMatchText : function(item) {
		return item.text + " " + item.value + " " + item.keywords;
	},
	_unwirePostBackEvent : function() {
		var element = this.get_element();
		if(this._postBackMode === Nws.UI.FilterableListBoxPostBackMode.OnChange)
			$removeHandler(element, "change", this._elementChangeDelegate);
		else if(this._postBackMode === Nws.UI.FilterableListBoxPostBackMode.OnClick)
			$removeHandler(element, "click", this._elementClickDelegate);
	},
	_wirePostBackEvent : function() {
		var element = this.get_element();
		if(this._postBackMode === Nws.UI.FilterableListBoxPostBackMode.OnChange)
			$addHandler(element, "change", this._elementChangeDelegate);
		else if(this._postBackMode === Nws.UI.FilterableListBoxPostBackMode.OnClick)
			$addHandler(element, "click", this._elementClickDelegate);
	},
	dispose : function() {
		var element = this.get_element();
	
		$removeHandler(this._filterTextBox, "keyup", this._filterTextBoxKeyupDelegate);
		this._unwirePostBackEvent();
	
		Nws.UI.FilterableListBox.callBaseMethod(this, "dispose");
	},
	filter : function(value) {
		this._valueInternal = value;
		var args = new Sys.CancelEventArgs();
		this.raiseFiltering(args);
		if(!args.get_cancel()) {
			if(this._delayTimeout)
				window.clearTimeout(this._delayTimeout);
			this._delayTimeout = window.setTimeout(Function.createDelegate(this, this._filterCallback), this._delayInterval);
		}
	},
	initialize : function() {
		Nws.UI.FilterableListBox.callBaseMethod(this, "initialize");
		
		var element = this.get_element();
		if(!$getStyle(this._filterTextBox, "width"))
			$setStyle(this._filterTextBox, "width", Sys.UI.DomElement.getBounds(element).width + "px");
			
		this.filter(this._filterTextBox.value);
		
		this._wirePostBackEvent();
		$addHandler(this._filterTextBox, "keyup", this._filterTextBoxKeyupDelegate);
	},
	raiseFiltered : function(args) {
		var handler = this.get_events().getHandler("filtered");
		if(handler)
			handler(this, args);
	},
	raiseFiltering : function(args) {
		var handler = this.get_events().getHandler("filtering");
		if(handler)
			handler(this, args);
	}
}
Nws.UI.FilterableListBox.registerClass("Nws.UI.FilterableListBox", Nws.UI.ControlBase);


Nws.UI.FilterableListBoxPostBackMode = function() {
}
Nws.UI.FilterableListBoxPostBackMode.prototype = {
	OnChange : 0,
	OnClick : 1
}
Nws.UI.FilterableListBoxPostBackMode.registerEnum("Nws.UI.FilterableListBoxPostBackMode");
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();