
/**
 * 
 * Плагин jquery.mselect.js
 * Простая замена стандартного элемента select.
 * 
 * Использование
 * $(selector).mselect()
 * $(selector).mselect("value")
 * $(selector).mselect("disable")
 * $(selector).mselect("enable")
 * $(selector).mselect("hide")
 * $(selector).mselect("show")
 * $(selector).mselect("onchange", function)
 * 
 * $(selector).mselect("clear")
 * $(selector).mselect("append", "title", "value")
 * 
 */

jQuery.fn.mselect = function(action, callback, value) {
	
	switch (action) {
	
		// Добавить пункт меню
		case "append": 
			if ($(this).data("mselect")) {
				var title = callback;
				if (value == undefined) value = callback;
				var li = $("<li/>").data("value", value).text(title).appendTo($(this).data("ul"));
				$("<option/>").attr("value", value).text(title).appendTo(this);
				// Обработчики для пунктов меню - Обновить
				setHandlersForMenuItems(this, li);
			}
			return $(this);
	
		// Очистить все пункты меню
		case "clear":
			if ($(this).data("mselect")) {
				$(this).data("ul").find("li").remove();
				$("option", this).remove();
			}
			return $(this);
	
		// Получить текущее значение 
		case "value": 
			return $(this).data("value");
		
		// Выключить управление
		case "disable":
			if ($(this).data("mselect")) {
				$(this).data("disabled", true);
				$(this).data("mselect").div.css("opacity", "0.20");
			}
			return $(this);
		
		// Включить управление
		case "enable":
			if ($(this).data("mselect")) {
				$(this).data("disabled", false);
				$(this).data("mselect").div.css("opacity", "1");
			}
			return $(this);
		
		// Скрыть элемент
		case "hide":
			if ($(this).data("mselect")) $(this).data("mselect").div.hide();
			return $(this);
		
		// Показать элемент
		case "show":
			if ($(this).data("mselect")) $(this).data("mselect").div.show();
			return $(this);
		
		// Задать обработчик события onChange
		case "onchange": 
			if ($(this).data("mselect")) {
				$(this).data("onchange", callback);
			}
			return $(this);
		
		// Создание управления
		default: {
		
			$(this).each(function() {
			
				var ul = convertSelectToUl(this);
				$(this).hide();
			
				var mselect = {
						sel: $(this),
						div: $("<div class='mselect'/>"),
						arrows: {
							up: "&#x25B2;",
							down: "&#x25BC;"
						},				
						items: {
							first: $("li:eq(0)", ul),
							all: $(ul)
						},
						selected: {
							div: $("<div class='selected'/>"), // Элемент с выбранным пунктом меню
							table: null, // Вспомогательная layout-таблица
							caption: $("<span class='caption'/>"), // Имя выбранного пункта меню
							arrow: $("<span class='arrow'/>") // Стрелка
						}
					};
				
				// Инициализация
				
				$(this)
					.data("value", mselect.items.first.attr("value"))
					.data("onchange", (this.onchange) ? this.onchange : function() {})
					.data("disabled", false)
					.data("mselect", mselect);
				
				mselect.div
					.insertBefore(ul)
					.append(mselect.selected.div)
					.append(mselect.items.all);
				
				mselect.selected.table = $("<table/>")
					.attr("width", "100%")
					.attr("border", "0")
					.attr("cellpadding", "0")
					.attr("cellspacing", "0")
					.append(
						$("<tbody/>")
							.append(
								$("<tr/>")
									.append($("<td class='caption'/>").append(mselect.selected.caption))
									.append($("<td class='arrow'/>").attr("align", "right").append(mselect.selected.arrow))
							)
					);
					
				mselect.selected.div.append(mselect.selected.table);
				mselect.selected.caption.text(mselect.items.first.text());
				mselect.selected.arrow.html(mselect.arrows.down);
				
				mselect.items.all.hide();
				
				// Расчет ширины
				
				/*
				// Установка ширины, если нужна фиксированная по самому длинному пункту меню
				mselect.div.width(
					mselect.items.all.outerWidth()
					+ 25 // Место под стрелку
				);
				*/
				// Корректировка для MSIE, если нужна ширина 100%
				if ($.browser.msie) mselect.selected.div.width("100%");
				
				mselect.items.all.width(
					mselect.div.outerWidth()
					- (($.browser.msie) ? 0 : mselect.items.all.outerWidth() - mselect.items.all.innerWidth())
				);
				
				// Обработчики событий
				
				var sel = $(this);
				
				mselect.div
					.mouseover(function() {
						if (!$(sel).data("disabled")) {
							mselect.selected.arrow.html(mselect.arrows.up);
							mselect.items.all.show();
						}
					})
					.mouseout(function() {
						if (!$(sel).data("disabled")) {
							mselect.selected.arrow.html(mselect.arrows.down);
							mselect.items.all.hide();
						}
					});
					
				setHandlersForMenuItems(this, $("li", $(this).data("ul")));	
			});		
				
			return $(this);
		
		}
		
	}
	
	// Конвертация select в ul
	function convertSelectToUl(sel) {
		var ul = $("<ul/>").insertBefore(sel);
		$(sel).find("option").each(function() {
			$("<li/>")
				.data("value", this.value)
				.text($(this).text())
				.appendTo(ul);
		});
		$(sel).data("ul", ul);
		return ul;
	}

	// Установка обработчиков для каждого пункта меню
	function setHandlersForMenuItems(sel, li) {
		li
			.mouseover(function() {
				$(this).addClass("hover");
			})
			.mouseout(function() {
				$(this).removeClass("hover");
			})
			.click(function() {
				var mselect = $(sel).data("mselect");
				mselect.selected.caption.text($(this).text());
				$(sel).data("value", $(this).data("value"));
				$(sel).val($(this).data("value"));
				mselect.selected.arrow.html(mselect.arrows.down);
				mselect.items.all.hide();
				$(sel).data("onchange").call(mselect.items.all);
			});	
	}

};
