﻿;(function($) {
	$.fn.autosuggest = function(options, args) {
		return this.each(function() {
			if (typeof options == "string") {
				var elem = $.data(this, "ui-autosuggest");
				elem[options].apply(elem, args);
			}
			else {
				return $.data(this, "ui-autosuggest", new $.autosuggest(this, options)); 
			}
		});
	};
	
	//default config options
	var defaults = {
		wrapperClassName: "numpadFld", // Класс, который будет использоваться для обвязки
		//this suffix will be appended to the selectbox's name and will be text input's name
		suffix: "__autosuggest",
		//the same as the previous, but for hidden input
		hiddenSuffix: "__autosuggestHidden",
		//rename original select, and call the hidden field the original name attribute?
		renameOriginal: true,
		//if provided, will be the value of the text input when it has no value and focus
		emptyText: "",
		//if true, selected option of the selectbox will be the initial value of the combo
		triggerSelected: true,
		dropUp: false,
		//called after dropdown list appears
		showListCallback: null,
		//called after dropdown list disappears
		hideListCallback: null,
		//called at the end of constructor
		initCallback: null,
		//called at the end of initEvents function
		initEventsCallback: null,
		//called when both text and hidden inputs values are changed
		changeCallback: null,
		//called when text input's value is changed
		textChangeCallback: null
	};

	//constructor
	//creates initial markup and does some initialization
	$.autosuggest = function(container, options) {
		if (!$sc.isSelect(container))
			return;
		
		this.isIE6 = $.browser.msie && /6.0/.test(navigator.userAgent);
		
		this.element = container;
		this.options = $.extend({}, defaults, options || {});
		var sb = $(this.element);

		if (!this.options.emptyText && sb.attr("emptyMessage")) {
			this.options.emptyText = sb.attr("emptyMessage");
		}
		size = this.element.getAttribute("width") || (window.getComputedStyle ? window.getComputedStyle(this.element, null)["width"] : (this.element.currentStyle ? this.element.currentStyle["width"] : 0));
		if ((!size) || (size == "auto"))
			size = this.element.offsetWidth || 100;

		this.elementWidth = parseInt(size || 100);
		
		if (!this.isIE6) {
			this.elementWidth += 1;
		}

		var origName = sb.attr("name");
		var currentSbValue = sb.val();

		// Создаем элементы обвязки
		// создаем обвязку для контрола
		this.wrapper = sb.wrap("<div>")
			.hide()
			.parent()
			.addClass(this.options.wrapperClassName)
			.addClass("autosuggest")
			//.css("float", "left")
			.css("zIndex", "0");
		
		// Текстовое поле для ввода значений
		this.input = $("<input type='text' />").
			appendTo(this.wrapper).
			attr("autocomplete", "off").
			attr("value", "").
			attr("name", origName + "__autosuggest");

		// Hidden поле для хранения выбранного значения
		this.hidden = $("<input type='hidden' />").
			appendTo(this.wrapper).
			attr("value", sb.children('option:selected').text()).
			attr("name", origName + "__selectHidden")
			.css("float", "none");

		// Кнопка для показа списка значений
		this.icon = $("<div />").
			appendTo(this.wrapper).
			addClass("as-button");

		this.popupWnd = $("<div />")
			.appendTo(this.wrapper)
			.addClass("as-popup-wnd")
			.addClass("invisible")
			.css("zIndex", "99999");
		
		if (this.isIE6) {
			this.iframe = $("<iframe />").appendTo(this.popupWnd);
		}
		
		// Контейнер для выподающего списка
		this.listWrapper = $("<div />")
			.appendTo(this.popupWnd)
			.addClass("list-wrapper");

		// Контейнер списка значений
		this.list = $("<ul />").appendTo(this.listWrapper);
		/*
		this.updateDrop();
		*/
		var self = this;
		this.buildList();
		/*
		this.createItems();
		this.listWrapper.addClass("invisible");
		*/
		if ($.browser.opera) {
			this.wrapper.css({ position: "relative", left: "0", top: "0" });
		}

		this.lastKey = null;

		this.multiple = sb.attr("multiple");

		this.wrapper.data("sc:lastEvent", "click");
		this.wrapper.data("sc:inputFocus", "");
		this.overflowCSS = "overflowY";
		
		
		this.notify("init");
		this.initEvents();
	};

	//shortcuts
	var $sc = $.autosuggest;
	$sc.fn = $sc.prototype = {};
	$sc.fn.extend = $sc.extend = $.extend;

	$sc.openedPopups = [];

	$sc.AddOpenedPopup = function(elt)
	{
		$sc.openedPopups.push(elt);
	}

	$sc.RemoveOpenedPopup = function(elt)
	{
		for (var i = 0; i < $sc.openedPopups.length; ++i)
		{
			if ($sc.openedPopups[i] == elt)
			{
				var z = [];
				$sc.openedPopups.splice(i, 1);
				break;
			}
		}
	}

	$sc.CloseAllOpenedPopups = function()
	{
		var copy = $sc.openedPopups.slice(0);
		for (var i = 0; i < copy.length; ++i)
		{
			copy[i].closePopup();
		}
	}

	$sc.fn.extend({
		initEvents: function() {
			var self = this;

			// Скрываем список, если он виден.
			$(document).bind("click", function(e) {
				if ((self.icon.get(0) != e.target) && (self.input.get(0) != e.target)) {
					//self.hideList();
					self.closePopup();
				}
			});

			this.icon.bind("click", function(e) {
				Utils.debug("icon click event");
				if (!self.input.attr("disabled")) {
					self.wrapper.data("sc:lastEvent", "click");
					//self.filter();
					//self.iconClick();
					self.filterList();
					self.toggleShowPopup();
				}
			});

			this.input.bind("click", function(e) {
				Utils.debug("input click event");
				if (self.wrapper.data("sc:processClickEvent") == "") {
					self.icon.trigger("click");
				}
				else {
					self.wrapper.data("sc:processClickEvent", "");
				}
			});

			// Перемещение курсора в списке с пом. указателя.
			this.listItems.bind("mouseover", function(e) {
				if ("LI" == e.target.nodeName.toUpperCase()) {
					self.highlight(e.target);
				}
				else {
					self.highlight($(e.target).parent());
				}
			});

			this.listItems.bind("click", function(e) {
				Utils.debug("listItems click event");
				setTimeout(function() { self.onListItemClick($(e.target)); }, 0);
			});

			// Обработка клавиш в контроле.
			this.input.bind("keydown", function(e) { 
				//Utils.debug("input keydown event");
				self.inputKeyDownEvent.call(self, e); 
			} );

			this.input.bind("keypress", function(e) {
				//Utils.debug("input keypress event");
				if ($sc.KEY.RETURN == e.keyCode) {
					e.preventDefault();
				}
				if ($sc.KEY.TAB == e.keyCode) {
					if (self.getPopupVisible())
						e.preventDefault();
				}
			});
			
			this.triggerSelected();
			/*
			this.applyEmptyText();
			*/
			// Устанавливаем фокус в поле
			this.input.bind("focus", function(e) {
				Utils.debug("input focus event");
				self._onInputFocus.call(self, e);
				//self.inputFocusEvent.call(self, e);
			});
			
			// Сбрасываем значение на дефолтовое, если введено несуществующее значение.
			this.input.bind("blur", function(e) { 
				Utils.debug("input blur event");
				self._onInputBlur.call(self, e);
				//self.inputBlurEvent.call(self, e); 
			});
			
			this.notify("initEvents");
		},

		getTextValue: function() {
			return this.__getValue("input");
		},

		setTextValue: function(value) {
			this.__setValue("input", value);
		},
		
		getHiddenValue: function() {
			return this.__getValue("hidden");
		},

		setHiddenValue: function(value) {
			return this.__setValue("hidden", value);
		},

		__getValue: function(prop) {
			prop = this[prop];
			return $.trim(prop.val());
		},

		__setValue: function(prop, value) {
			prop = this[prop];
			prop.val(value);
		},

		// Позийионирование выпадающего списка
		locatePopupWnd: function() {
			var pos = this.input.position();
			pos.top = pos.top + this.input.outerHeight();
                        //pos.left -= ($('body').offset().left || $('body > div:visible').eq(0).offset().left);
			if (this.isIE6) {
				pos.left -= 1; 
			}
			this.popupWnd.css("left", pos.left).css("top", pos.top);
		},
		
		// Отображаем или скрываем элемент в зависимости от состояния
		toggleShowPopup: function() {
			if (this.getPopupVisible()) {
				this.closePopup();
			}
			else {
				this.showPopup();
			}
		},
		
		// Выводит на экран выпадающий список
		showPopup: function() {
			if (!this.getPopupVisible()) {
				Utils.debug("showPopup");
				this.locatePopupWnd();

				if (this.elementWidth <= 1) { // hidden element fix for opera
					this.elementWidth = $(this.element).width() || 200;
				}
				this.resizeWnd();
				this.wrapper.css("zIndex", "99999");
				//this.filterList();
				
				this.popupWnd.removeClass("invisible").addClass("visible");
				this.input.focus();
				this.highlightSelected();
				if (this.wrapper.data("sc:lastEvent") == "click" && this.input.val().length) {
					this.selection(this.input.get(0), 0, this.input.val().length);
				}

				$sc.AddOpenedPopup(this);
			}
		},
		
		// Скрывает выпадающий список
		closePopup: function() {
			if (this.getPopupVisible()) {
				Utils.debug("closePopup");
				this.wrapper.css("zIndex", "0");
				this.popupWnd.removeClass("visible").addClass("invisible");
				$sc.RemoveOpenedPopup(this);
			}
		},
		
		// Определяет отображено ли окно или нет
		// Возвращает:
		// true - выпадающий список отображен на экране
		// иначе - false
		getPopupVisible: function() {
			return this.popupWnd.hasClass("visible");
		},
		
		// Устанавливает размеры окна для выпадающего списка
		resizeWnd: function() {
			this.setPopupWidth(this.elementWidth);
		},
		
		// Устанавливаем ширину выпадающего списка
		setPopupWidth: function(width) {
			this.popupWnd.width(width);
			if (this.isIE6) {
				this.iframe.width(this.popupWnd.width());
			}
			this.listWrapper.width(width);
		},
		
		// Устанавлливаем высоту выпадающего списка
		setPopupHeigth: function(height) {
			this.listWrapper.height(height);
			this.popupWnd.height(height);
			
			if (this.isIE6) {
				this.iframe.height(this.popupWnd.height());
			}
		},
		
		onListItemClick: function(item) {
			this.setComboValue(item.text(), true, true);
			//this.applyEmptyText();
			this.wrapper.data("sc:inputFocus", "click");
			this.input.focus();
			this.wrapper.data("sc:inputFocus", "");
		},

		_onInputFocus: function(ev) {
			if (this.wrapper.data("sc:inputFocus") == "" ) { 
				this.wrapper.data("sc:processClickEvent", "");
				
				if (!this.input.attr("disabled")) {
					
					this.removeEmptyText();
					//this.wrapper.data("");
					
					var currentTextValue = this.getTextValue();
					
					if (currentTextValue == "" && !this.getPopupVisible()) {
						this.wrapper.data("sc:processClickEvent", "false");
						this.wrapper.data("sc:lastEvent", "click");
						this.filterList();
						this.showPopup();
					}
				}
			}
		},
		
		_onInputBlur: function(ev) {
			this.wrapper.data("sc:processClickEvent", "");
			
			var textValue = this.getHiddenValue();
			
			if ($.trim(textValue) == "") {
				
				for (var i = 0, len = this.items.length; i < len; i++) {
					
					var item = $(this.items.get(i));
					
					if (item.attr("selected")) {
						textValue = item.text();
						break;
					}
				}
			}
			
			textValue = $.trim(textValue);
			
			if (textValue != "") {
				this.setTextValue(textValue);
			}
			else {
				this.setTextValue("");
				this.applyEmptyText();
			}
		},
		
		removeEmptyText: function() {
			if (this.input.hasClass("empty")) {
				this.input.removeClass("empty").val("");
			}
		},
		
		applyEmptyText: function() {
			if (!this.options.emptyText.length)
				return;
			
			if ("" == this.input.val()) {
				this.input.addClass("empty").val(this.options.emptyText);
			}
			else if (this.input.hasClass("empty")) {
				this.input.removeClass("empty");
			}
		},
		
		// Создаем список опций
		buildList: function() {
			Utils.debug("buildList");
			this.items = $(this.element).children().filter("option");
			
			this.list.empty();
			this.listItems = this.list.children();
			
			if (this.items.length == 0) {
				return;
			}
			
			var maxOptionWidth = 0;
			
			
			for (var i = 0, len = this.items.length; i < len; i++) {
				var item = this.items.get(i);
				var optionText = $.trim($(item).text());
				var liElem = $("<li />").appendTo(this.list).html("<span>" + optionText + "</span>").addClass("visible");
				
				var elWigth = liElem.find("span").outerWidth();
				if (maxOptionWidth < elWigth) {
					maxOptionWidth = elWigth;
				}
			}
//var optionList = '';
//for (var i = 0, len = this.items.length; i < len; i++) {
//	var item = this.items[i];
//	var optionText = $.trim($(item).text());
//	optionList += '<li class="visible"><span>' + optionText + '</span></li>';
//}
//this.list.html(optionList);
			
			// Выравниваем ширину списка по элементу
			if (maxOptionWidth < this.elementWidth) {
				maxOptionWidth = this.elementWidth;
			}
			
			// Задаем ширину для списка
			//this.setPopupWidth(maxOptionWidth);

			this.listItems = this.list.children();
			
			// Определяем высоду одного элемента в списке
			// Если значений нет, то высота списка равна 0 и он не отображается.
			this.singleItemHeight = 0;
			
			if (this.listItems.length != 0) {
				this.popupWnd.removeClass("invisible").addClass("visible");
				this.singleItemHeight = this.listItems.outerHeight();
				this.popupWnd.removeClass("visible").addClass("invisible");
			}
		},
		
		// Фильтруем список для отображения
		filterList: function() {
			Utils.debug("filterList");
			
			if ("yes" == this.wrapper.data("sc:optionsChanged")) {
				this.buildList();
				
				var self = this;
				
				this.listItems.bind("mouseover", function(e) {
					self.highlight(e.target);
				})
				.bind("click", function(e) {
					Utils.debug("listItems click event");
					setTimeout(function() { self.onListItemClick($(e.target)); }, 0);
				});

				this.wrapper.data("sc:optionsChanged", "");
			}
			
			var currentTextValue = this.getTextValue();
			
			
			var lev = "click" == this.wrapper.data("sc:lastEvent");
			for (var i = 0, len = this.listItems.length; i < len; i++) {
				var item = $(this.listItems.get(i));
				
				var itemValue = item.text();
				var isTextChanged = false;
				
				if (item.hasClass("visible")) {
					isTextChanged = true;
				}
				
				var classToRemove = "invisible";
				var classToAdd = "visible";
				
				if (!lev) {
					var currValRegExp = new RegExp("(^|\\s)(" + currentTextValue + ")", "ig");
					if (currValRegExp.test(itemValue)) {
						Utils.debug(itemValue);
						itemValue = itemValue.replace(currValRegExp, "$1<span class=\"selected\">$2</span>");
						isTextChanged = true;
					} else {
						var classToRemove = "visible";
						var classToAdd = "invisible";
					}
					delete currValRegExp;
				}
				
				item.removeClass(classToRemove).addClass(classToAdd);
				
				if (isTextChanged) {
					item.html(itemValue);
				}
			}
			this.setOverflow();
			this.setListHeight();
			if (!lev) {
				this.highlightSelected();
			}
		},
		
		getSingleItemHeight: function() {
			if (!this.singleItemHeight || this.singleItemHeight == 0) {
				//this.singleItemHeight = 21;
				
				if (this.listItems.length != 0) {
					this.popupWnd.removeClass("invisible").addClass("visible");
					this.singleItemHeight = this.listItems.outerHeight();
					this.popupWnd.removeClass("visible").addClass("invisible");
				}
			}
			return this.singleItemHeight;
		},
		
		//returns sum of all visible items height
		getListItemsHeight: function() {
			var itemHeight = this.getSingleItemHeight() ;
			return (itemHeight + 1) * this.liLen();
		},

		//changes list wrapper's overflow from hidden to scroll and vice versa (depending on list items height))
		setOverflow: function() {
			var maxHeight = this.getListMaxHeight();

			if (this.getListItemsHeight() > maxHeight)
				this.listWrapper.css(this.overflowCSS, "scroll");
			else
				this.listWrapper.css(this.overflowCSS, "hidden");
		},

		//highlights active item of the dropdown list
		highlight: function(activeItem) {
			//if (($sc.KEY.DOWN == this.lastKey) || ($sc.KEY.UP == this.lastKey))
			//	return;

			this.listItems.removeClass("active");
			$(activeItem).addClass("active");
		},

		//sets text and hidden inputs value
		setComboValue: function(val, pop, closePopup) {
			var oldVal = this.input.val();

			var v = $.trim(val);
			this.input.val(v);
			this.setHiddenValue(val);
			
			if (closePopup) {
				this.closePopup();
			}
			else {
				this.filterList();
			}
			this.input.removeClass("empty");

			if (this.input.val() != oldVal)
				this.notify("textChange");
		},

		// Устанавливаем значение в скрытом поле.
		// Если введенное значение присутствует в списке селекта, то устанавливаем новое значение в селекте
		// Если введенное значение не найдено в селекте, то текущее значение в селекте не меняем.
		// Значение текстового поля в этом сл будет обновлено при потере фокуса. Будет установлено текущее значение из селекта
		// или будет выбрано пустое значение.
		setHiddenValue: function(val) {
			var set = false;
			val = $.trim(val);
			var oldVal = this.hidden.val();

			if (val == $.trim(oldVal)) {
				return;
			}
			
			var confirmCalback = function() {
				for (var i = 0, len = this.items.length; i < len; ++i) {
					if (val == $.trim(this.items.eq(i).text())) {
						this.hidden.val(this.items.eq(i).text());
						set = true;
						break;
					}
				}
				
				// Введенное значение найдено в списке селекта
				if (set) {
					
					var currentVal = this.hidden.val();
					
					if (oldVal != currentVal){
						this.input.val(currentVal);
						//$(this.element).val(this.hidden.val()); don't work in JQuery 1.4
						//var selValue = $("option[text='" + currentVal +"']", this.element).val(); don't work in jQuery 1.6
						
						var select = $(this.element);
						select.children('option').each(function() {
							if (this.text == currentVal) {
								$(select).val(this.value).change()/*.click()*/;
								try {
									if ($.validator && $(select).closest('form').validate()) 
										$(select).closest('form').validate().element($(select));									
								} catch (e) {
									if (window.console) console.error(e);
								}
								$(this.input).focus();
								return false;
							}
						});

					}
				}
			}
			
			var cancelCalback = function() {
				this.input.val(this.hidden.val());
			}

			var args = new ConfirmationEventArgs(this, confirmCalback, cancelCalback);
			
			if (this.options.changeCallback) {
				this.options.changeCallback.call(this, args);
			}
			else {
				args.confirm();
			}
		},
		
		//just returns integer value of list wrapper's max-height property
		getListMaxHeight: function() {
			var result = parseInt(this.popupWnd.css("maxHeight"), 10);
			if (isNaN(result)) {
				result = this.getSingleItemHeight() * 10;
			}

			return result;
		},

		//corrects list wrapper's height depending on list items height
		setListHeight: function() {

			var liHeight = this.getListItemsHeight();
			var maxHeight = this.getListMaxHeight();
			var listHeight = this.popupWnd.height();
			
			if (liHeight < listHeight) {
				//this.listWrapper.height(liHeight);
				this.setPopupHeigth(liHeight);
				return liHeight;
			}
			else if (liHeight > listHeight) {
				var lHeigth = Math.min(maxHeight, liHeight)
				this.setPopupHeigth(lHeigth);
				
				return lHeigth;
			}

		},

		//returns active (hovered) element of the dropdown list
		getActive: function() {
			return this.listItems.filter(".active");
		},

		acceptCurrentItem: function() {
			// Выбираем текущее значение в списке
			this.setComboValue(this.getActive().text(), true, true);
			this.wrapper.data("sc:inputFocus", "click");
			this.input.focus();
			this.wrapper.data("sc:inputFocus", "");
		},
		
		inputKeyDownEvent: function(e) {
			//Utils.debug("input keydown event");
			//Utils.debug("Alt: " + e.altKey + " Ctrl: " + e.ctrlKey + " Shift: " + e.shiftKey + " keyCode: " + e.keyCode);
			this.wrapper.data("sc:lastEvent", "keydown");
			
			var k = $sc.KEY;
			
			switch (e.keyCode) {
				case k.RETURN:
					this.acceptCurrentItem();
					break;
				case k.TAB:
					
					if (this.getPopupVisible()) {
						// Нажат Tab при открытом списке
						e.preventDefault();
						this.acceptCurrentItem();
					}
					
					break;
				case k.DOWN:
				case k.UP:
					
					if (e.altKey && !e.ctrlKey && !e.shiftKey)
					{
						// Нажали Alt+Down или Alt+Up
						if (this.getPopupVisible()) {
							// Cкрываем список
							this.closePopup();
						}
						else {
							// Показываем список
							this.showPopup();
							this.input.focus();
						}
					}
					else
					{
						switch (e.keyCode) {
							case k.DOWN:
								this.highlightNext();
								break;
							case k.UP:
								this.highlightPrev();
								break;
						}
					}

					break;
				case k.ESC:
					
					if (this.getPopupVisible()) {
						this.closePopup();
					}
					
					break;
				case k.CTRL:
				case k.SHIFT:
				case k.ALT:
					break;
				default:
					this.inputChanged();
					break;
			}				
		},


		//returns number of currently visible list items
		liLen: function() {
			return this.listItems.filter(".visible").length;
		},

		//triggered when the user changes combo value by typing
		inputChanged: function() {
			var self = this;
			var callback = function() {
				
				this.filterList();
				
				if (this.liLen()) {
					if (!this.getPopupVisible()) {
						this.showPopup();
					}
					else {
						this.setOverflow();
						this.setListHeight();
					}
				} else {
					this.closePopup();
				}
				
				this.notify("textChange");
			}
			
			setTimeout(function() { callback.call(self) }, 0);
		},

		//highlights first item of the dropdown list
		highlightFirst: function() {
			this.listItems.removeClass("active").filter(".visible:eq(0)").addClass("active");
			this.listWrapper.scrollTop(0);
		},

		highlightSelected: function() {
			this.listItems.removeClass("active");
			var val = $.trim(this.input.val());

			var isItemFound = false;
			
			if (val != "") {
				var list = this.listItems.filter(".visible");
				for (var i = 0, len = list.length; i < len; i++) {
					var item = $(list.get(i));
					if (item.text() == val) {
						isItemFound = true;
						item.addClass("active");
						//this.listWrapper.scrollTop(0);
						this.scrollDown();
						break;
					}
				}
			}
			if (!isItemFound) {
				this.highlightFirst();
			}
		},

		//highlights item of the dropdown list next to the currently active item
		highlightNext: function() {
			var $next = this.getActive().next();

			while ($next.hasClass("invisible") && $next.length) {
				$next = $next.next();
			}

			if ($next.length) {
				this.listItems.removeClass("active");
				$next.addClass("active");
				this.scrollDown();
			}
		},

		//scrolls list wrapper down when needed
		scrollDown: function() {
			if ("scroll" != this.listWrapper.css(this.overflowCSS))
				return;

			var beforeActive = this.getActiveIndex() + 1;

			var minScroll = this.listItems.outerHeight() * beforeActive - this.listWrapper.height();

			minScroll += beforeActive;

			var st = this.listWrapper.scrollTop();
			
			if (st < minScroll) {
				this.listWrapper.scrollTop(minScroll);
			}
		},


		//highlights list item before currently active item
		highlightPrev: function() {
			var $prev = this.getActive().prev();

			while ($prev.length && $prev.hasClass("invisible"))
				$prev = $prev.prev();

			if ($prev.length) {
				this.getActive().removeClass("active");
				$prev.addClass("active");
				this.scrollUp();
			}
		},

		//returns index of currently active list item
		getActiveIndex: function() {
			return $.inArray(this.getActive().get(0), this.listItems.filter(".visible").get());
		},


		//scrolls list wrapper up when needed
		scrollUp: function() {

			if ("scroll" != this.listWrapper.css(this.overflowCSS))
				return;

			var beforeActive = this.getActiveIndex() + 1;
			var maxScroll = beforeActive * this.listItems.outerHeight() /*+ this.listWrapper.height()*/;

			maxScroll += beforeActive;
			
			var st = this.listWrapper.scrollTop();
			
			if ((maxScroll - st) < this.getSingleItemHeight()) {
				maxScroll -= this.getSingleItemHeight();
				this.listWrapper.scrollTop(maxScroll);
			}
		},

		//triggerSelected stuff
		triggerSelected: function() {
			if (!this.options.triggerSelected)
				return;

			var isSelectedNotFount = true;
			for (var i = 0, len = this.items.length; i < len; i++) {
				var item = $(this.items.get(i));
				
				if (item.attr("selected")) {
					isSelectedNotFount = false;
					this.setComboValue(item.text(), false, true);
					break;
				}
			}
			
			if (isSelectedNotFount) {
				this.setComboValue(this.items.eq(0).text(), false, false);
				this.input.trigger("blur");
			}
		},

		//provides selection for autofilling
		//borrowed from jCarousel
		selection: function(field, start, end) {
			if (field.createTextRange) {
				var selRange = field.createTextRange();
				selRange.collapse(true);
				selRange.moveStart("character", start);
				selRange.moveEnd("character", end);
				selRange.select();
			} else if (field.setSelectionRange) {
				field.setSelectionRange(start, end);
			} else {
				if (field.selectionStart) {
					field.selectionStart = start;
					field.selectionEnd = end;
				}
			}
		},

		//for internal use
		updateDrop: function() {
			if (this.options.dropUp)
				this.listWrapper.addClass("list-wrapper-up");
			else
				this.listWrapper.removeClass("list-wrapper-up");
		},

		//updates dropUp config option
		setDropUp: function(drop) {
			this.options.dropUp = drop;
			this.updateDrop();
		},

		notify: function(evt) {
			$.event.trigger(evt, this);
		}
	});

	$sc.extend({
		//key codes
		//from jCarousel
		KEY: {
			UP: 38,
			DOWN: 40,
			DEL: 46,
			TAB: 9,
			RETURN: 13,
			ESC: 27,
			COMMA: 188,
			PAGEUP: 33,
			PAGEDOWN: 34,
			BACKSPACE: 8,
			SHIFT: 16,
			CTRL: 17,
			ALT: 18
		},

		isSelect: function(element) {
			return element.tagName.toUpperCase() == "SELECT";
		},

		/*
		 * Активация элемента
		 */
		deactivate: function($select) {
			$select = $($select);
			//debug("deactivate element " + $select.attr("id"));
			
			$select.each(function() {
				var $this = $(this);
				
				$this.attr("disabled", true);
				
				if ($sc.isSelect(this) && $this.is(".autosuggest")) {
					$this.parent().find("input[type='text']").attr("disabled", true).addClass("disable");
				}
			});
		},

		/*
		 * Деактивация элемента
		 */
		activate: function($select) {
			$select = $($select);
			//debug("activate element " + $select.attr("id"));
			
			$select.each(function() {
				var $this = $(this);
				
				$this.removeAttr("disabled");
				
				if ($sc.isSelect(this) && $this.is(".autosuggest")) {
					$this.parent().find("input[type='text']").removeAttr("disabled").removeClass("disable");
				}
			});
		},

		changeOptions: function($select) {
			$select = $($select);
			$select.each(function() {
				if (! $sc.isSelect(this)) {
					return;
				}

				var $this = $(this);
				var $wrapper = $this.parent();
				var $input = $wrapper.find("input[type='text']");
				
				var $listWrapper = $wrapper.find("ul").parent();

				/*$listWrapper.removeClass("visible").
					addClass("invisible");*/
				$wrapper.css("zIndex", "0");
				/*$listWrapper.css("zIndex", "99999");*/

				$input.val("");
				$wrapper.data("sc:optionsChanged", "yes");
				var $selectbox = $this;
				var parent = $selectbox.parent(); 
				var option = $selectbox.find("option:selected");
				parent.find("input[type='text']").val(option.text());
				parent.find("input[type='hidden']").val(option.text());
				parent.data("sc:lastEvent", "click");
				var elem = $.data(this, "ui-autosuggest");
				if (elem != null) {
					elem.applyEmptyText();
				}
			});
		},

		readonly: function($select) {
			$select = $($select);
			$select.each(function() {
				if (! $sc.isSelect(this)) {
					return;
				}
				
				var $this = $(this);
				var $wrapper = $this.parent();
				if ($wrapper) {
					var $input = $wrapper.find("input[type='text']");
					if ($input) {
						$input.attr("readonly", true);
					}
				}
			});
		}
	});
})(jQuery); 
