﻿/*
-------------------------------------
cusel version 2.3
change of standard select to styled one
autor: Evgen Ryzhkov
www.xiper.net
----------------------------------------	
*/
function cuSel(params) {
	jQuery(document).ready(function(){
			
		jQuery(params.changedEl).each(function(num){
			var chEl = jQuery(this),
			chElWid = chEl.outerWidth(), // select width
			chElClass = chEl.attr("class"), // select class
			chElId = chEl.attr("id"), // id
			chElName = chEl.attr("name"), // имя
			defaultVal = chEl.val(), // initial value
			activeOpt = chEl.find("option[value="+defaultVal+"]").eq(0),
			defaultText = activeOpt.text(), // initial text
			disabledSel = chEl.attr("disabled"), // if select is blocked
			scrollArrows = params.scrollArrows,
			chElOnChange = chEl.attr("onchange"),
			chElTab = chEl.attr("tabindex");

			if(!chElId)	return false; // do not stylize the select if id is not specified
			if (!disabledSel) {
				classDisCuselText = "", // to track click on disabled select
				classDisCusel=""; // for disabled select design
			}
			else {
				classDisCuselText = "classDisCuselLabel";
				classDisCusel="classDisCusel";
			}
			if (scrollArrows) {
				classDisCusel+=" cuselScrollArrows";
			}
			activeOpt.addClass("cuselActive");  // highlighting class is at once added to an active option
			var optionStr = chEl.html(), // options list
			// option tags are replaced with span tags,completely preserving initial structure
			spanStr = optionStr.replace(/option/ig,"span");
			//if z-index check is needed, we check if already created selects are available and set z-index to a new one taking into account existing ones
			//if (params.checkZIndex) {
            if (true) {
				num = jQuery(".cusel").length;
			}
			// styled select frame
			var cuselFrame = '<div class="cusel '+chElClass+' '+classDisCusel+'"'+
							' id=cuselFrame-'+chElId+
							' style="width:'+chElWid+'px"'+
							' tabindex="'+chElTab+'"'+
							'>'+
							'<div class="cuselFrameRight"></div>'+
							'<div class="cuselText">'+defaultText+'</div>'+
							'<div class="cusel-scroll-wrap"><div class="cusel-scroll-pane" id="cusel-scroll-'+chElId+'">'+
							spanStr+
							'</div></div>'+
							'<input type="hidden" id="'+chElId+'" name="'+chElName+'" value="'+defaultVal+'" />'+
							'</div>';
							
							
			// delete standard select, replace it with styled one
			chEl.replaceWith(cuselFrame);
			// if onchange was engaged - engage with the field
			if (chElOnChange) jQuery("#"+chElId).bind('change',chElOnChange);
			/* set height of the drop-down lists based on the number of visible positions and height of one position
			provided that only those having the number of options more than the set number of visible ones */
			var newSel = jQuery("#cuselFrame-"+chElId),
			arrSpan = newSel.find("span"),
			defaultHeight;
			if (!arrSpan.eq(0).text()) {
				defaultHeight = arrSpan.eq(1).outerHeight();
				arrSpan.eq(0).css("height", arrSpan.eq(1).height());
			} 
			else {
				defaultHeight = arrSpan.eq(0).outerHeight();
			}		
			
			if (arrSpan.length>params.visRows) {
				newSel.find(".cusel-scroll-wrap").eq(0)
				.css({
					height: defaultHeight*params.visRows+"px",
					display : "none",
					visibility: "visible"
				})
				.children(".cusel-scroll-pane").css({
					height: defaultHeight*params.visRows+"px"
				});
			}
			else {
				newSel.find(".cusel-scroll-wrap").eq(0).css({
					display : "none",
					visibility: "visible"
				});
			}
			// insert additional tags into options
			var arrAddTags = jQuery("#cusel-scroll-"+chElId).find("span[addTags]"),
			lenAddTags = arrAddTags.length;
			for (i=0;i<lenAddTags;i++) arrAddTags.eq(i).append(arrAddTags.eq(i).attr("addTags")).removeAttr("addTags");
			
		});

		/*
		------------------------------------------------------------------------------
		binding of the events with the selects
		------------------------------------------------------------------------------
		*/
		jQuery("html").unbind("click");
		jQuery("html").click(function(e){
			var clicked = jQuery(e.target),
			clickedId = clicked.attr("id"),
			clickedClass = clicked.attr("class");
				
			// if clicked on select itself (text)
			if ((clickedClass.indexOf("cuselText")!=-1 || clickedClass.indexOf("cuselFrameRight")!=-1) && clicked.parent().attr("class").indexOf("classDisCusel")==-1) {
				var cuselWrap = clicked.parent().find(".cusel-scroll-wrap").eq(0);
				
				// if drop-down menu is hidded - show it up
				if (cuselWrap.css("display")=="none") {
					jQuery(".cusel-scroll-wrap").css({
						display: "none"
					});
					cuselWrap.show("slide", { direction: "up" }, 250);
					var cuselArrows = false;
					if (clicked.parents(".cusel").attr("class").indexOf("cuselScrollArrows")!=-1) cuselArrows=true;
					if (!cuselWrap.find(".jScrollPaneContainer").eq(0).is("div")) {
						cuselWrap.find("div").eq(0).jScrollPaneCusel({
							showArrows: cuselArrows
						});
					}
				}
				else {
					cuselWrap.hide("slide", { direction: "up" }, 250);
				}
			}
			// if clicked on select itself (container)
			else if (clickedClass.indexOf("cusel")!=-1 && clickedClass.indexOf("classDisCusel")==-1 && clickedClass.indexOf("cuselActive")==-1) {
				var cuselWrap = clicked.find(".cusel-scroll-wrap").eq(0);
				/* if drop-down menu is hidden - show it up */
				if(cuselWrap.css("display")=="none") {
					jQuery(".cusel-scroll-wrap").css({
						display: "none"
					});
					cuselWrap.show("slide", { direction: "up" }, 250);
					var cuselArrows = false;
					if (clicked.attr("class").indexOf("cuselScrollArrows")!=-1) cuselArrows=true;
					if (!cuselWrap.find(".jScrollPaneContainer").eq(0).is("div")) {
						cuselWrap.find("div").eq(0).jScrollPaneCusel({
							showArrows: cuselArrows
						});
					}
				}
				else {
					cuselWrap.css({
						display: "none"
					});
				}
			}
			/* if chose a position in the list */
			else if (clicked.is("span") && clicked.parents(".cusel-scroll-wrap").is("div")) {
				var clickedVal;
				(clicked.attr("value") == undefined) ? clickedVal=clicked.text() : clickedVal=clicked.attr("value");
				clicked.parents(".cusel-scroll-wrap").find(".cuselActive").eq(0).removeClass("cuselActive")
					.end().parents(".cusel-scroll-wrap")
					.next().val(clickedVal)
					.end().prev().text(clicked.text())
					.end().css("display","none");
					
				clicked.addClass("cuselActive");
				if(clickedClass.indexOf("cuselActive")==-1)	clicked.parents(".cusel").find(".cusel-scroll-wrap").eq(0).next("input").change(); // so onchenge worked out
			}
			else if(clicked.parents(".cusel-scroll-wrap").is("div")) {
				return;
			}
			// hide open lists, if clicked out of the list
			else {
				jQuery(".cusel-scroll-wrap").css("display","none");
			}
		});

		// pseudo-classes css focus and hover dubbing for IE6-7
		jQuery(".cusel").click(function() {
			if (!jQuery(this).hasClass("cuselFocus")) {
				jQuery(this).addClass("cuselFocus");
			}
			else {
				jQuery(this).removeClass("cuselFocus");
			}
		});

		jQuery(".cusel").blur(function() {
			jQuery(this).removeClass("cuselFocus");
		});

		jQuery(".cusel").hover(function() {
			jQuery(this).addClass("cuselHovered");
		},
		function() {
			jQuery(this).removeClass("cuselHovered");
		});
		
		jQuery(".cusel").unbind("keydown"); // in order to escape double triggering of the events
		jQuery(".cusel").keydown(function(event) {
			// if select is disabled, only tub working
			var key, keyChar;
			if (window.event) key=window.event.keyCode;
			else if (event) key=event.which;
			if (key==null || key==0 || key==9) return true;
			if (jQuery(this).attr("class").indexOf("classDisCusel")!=-1) return false;
			// if pressed arrow down
			if (key==40) {
				var cuselOptHover = jQuery(this).find(".cuselOptHover").eq(0);
				if (!cuselOptHover.is("span")) var cuselActive = jQuery(this).find(".cuselActive").eq(0);
				else var cuselActive = cuselOptHover;
				var cuselActiveNext = cuselActive.next();
				if (cuselActiveNext.is("span")) {
					jQuery(this).find(".cuselText").eq(0).text(cuselActiveNext.text());
					cuselActive.removeClass("cuselOptHover");
					cuselActiveNext.addClass("cuselOptHover");
					/* scroll to a selected element*/
					var scrollWrap = jQuery(this).find(".cusel-scroll-pane").eq(0);
					if(scrollWrap.parent().find(".jScrollPaneTrack").eq(0).is("div")) {
						var idScrollWrap = scrollWrap.attr("id"),
							hOption = scrollWrap.find("span").eq(0).outerHeight();
						jQuery("#"+idScrollWrap)[0].scrollBy(hOption);
					}
					return false;
				}
				else return false;
			}
			
			// if pressed arrow up
			if (key==38) {
				var cuselOptHover = jQuery(this).find(".cuselOptHover").eq(0);
				if (!cuselOptHover.is("span")) var cuselActive = jQuery(this).find(".cuselActive").eq(0);
				else var cuselActive = cuselOptHover;
				cuselActivePrev = cuselActive.prev();
					
				if (cuselActivePrev.is("span")) {
					jQuery(this).find(".cuselText").eq(0).text(cuselActivePrev.text());
					cuselActive.removeClass("cuselOptHover");
					cuselActivePrev.addClass("cuselOptHover");
					
					// scroll to a selected element
					var scrollWrap = jQuery(this).find(".cusel-scroll-pane").eq(0);
						
					if (scrollWrap.parent().find(".jScrollPaneTrack").eq(0).is("div")) {
						var idScrollWrap = scrollWrap.attr("id"),
							hOption = -parseInt(scrollWrap.find("span").eq(0).outerHeight());
						jQuery("#"+idScrollWrap)[0].scrollBy(hOption);
					}
					
					return false;
				}
				else return false;
			}
			
			// if pressed esc
			if (key==27) {
				var cuselActiveText = jQuery(this).find(".cuselActive").eq(0).text();
				jQuery(this)
					.find(".cusel-scroll-wrap").eq(0).css("display","none")
					.end().find(".cuselOptHover").eq(0).removeClass("cuselOptHover");
				jQuery(this).find(".cuselText").eq(0).text(cuselActiveText);
			}
			
			// if pressed enter
			if (key==13) {
				
				var cuselHover = jQuery(this).find(".cuselOptHover").eq(0);
				if (cuselHover.is("span")) {
					jQuery(this).find(".cuselActive").removeClass("cuselActive");
					var cuselHoverVal = cuselHover.attr("value");
					cuselHover.addClass("cuselActive");
				}
				else var cuselHoverVal = jQuery(this).find(".cuselActive").attr("value");
				
				jQuery(this)
					.find(".cusel-scroll-wrap").eq(0).css("display","none")
					.end().find(".cuselOptHover").eq(0).removeClass("cuselOptHover");
				jQuery(this).find("input").eq(0)
					.val(cuselHoverVal)
					.change();
			}
				
			if (jQuery.browser.opera) return false; /* specially for Opera, to prevent browser window from scrolling when the keys are pressed*/

		});

		/*
		------------------------------------------------------------------------------
		feature of sorting by pressed symbols (от Alexey Choporov)
		sorting continues until pause between symbols pressing reaches 0.5 sec
		keypress needed for pressed key symbol capture
		------------------------------------------------------------------------------
		*/
		var arr = [];
		jQuery(".cusel").keypress(function(event) {
			var key, keyChar;
			if (window.event) key=window.event.keyCode;
			else if (event) key=event.which;
			if (key==null || key==0 || key==9) return true;
			if (jQuery(this).attr("class").indexOf("classDisCusel")!=-1) return false;
			var o = this;
			arr.push(event);
			clearTimeout(jQuery.data(this, 'timer'));
			var wait = setTimeout(function() { handlingEvent() }, 500);
			jQuery(this).data('timer', wait);
			function handlingEvent() {
				var charKey = [];
				for (var iK in arr) {
					if (window.event)charKey[iK]=arr[iK].keyCode;
					else if (arr[iK])charKey[iK]=arr[iK].which;
					charKey[iK]=String.fromCharCode(charKey[iK]).toUpperCase();
				}
				var arrOption=jQuery(o).find("span"),colArrOption=arrOption.length,i,letter;
				for (i=0;i<colArrOption;i++) {
					var match = true;
					for (var iter in arr) {
						letter=arrOption.eq(i).text().charAt(iter).toUpperCase();
						if (letter!=charKey[iter]) {
							match=false;
						}
					}
					if (match) {
						jQuery(o).find(".cuselOptHover").removeClass("cuselOptHover").end().find("span").eq(i).addClass("cuselOptHover").end().end().find(".cuselText").eq(0).text(arrOption.eq(i).text());
						var scrollWrap=jQuery(o).find(".cusel-scroll-pane").eq(0);
						if (scrollWrap.parent().find(".jScrollPaneTrack").eq(0).is("div")) {
							var idScrollWrap=scrollWrap.attr("id"),hOption=scrollWrap.find("span").eq(0).outerHeight()-0.2;
							jQuery("#"+idScrollWrap)[0].scrollTo(hOption*i);
						}
						arr = arr.splice;
						arr = [];
						break;
						return true;
					}
				}
				arr = arr.splice;
				arr = [];
			}
			if(jQuery.browser.opera && window.event.keyCode!=9) return false;
		});

		jQuery(".cusel span").mouseover(function() {
			jQuery(this).parent().find(".cuselOptHover").eq(0).removeClass("cuselOptHover");
		});

		/* mark selects with z-index, taken out separately,
		to escape problems with the dynamically added selects and initializing selects in many ways */
		var arrCusel = jQuery(".cusel"),
		colCusel = arrCusel.length-1,
		i;
		for (i=0;i<=colCusel;i++) {
			arrCusel.eq(i).css("z-index",colCusel-i);
		}
		
	});
}

function cuSelRefresh(params) {
	/*
	------------------------------------------------------------------------------
	set height of the drop-down lists based on the number of visible positions and height of one position
	provided that only those having the number of options more than the set number of visible ones
	------------------------------------------------------------------------------
	*/
	var arrRefreshEl = params.refreshEl.split(","),
	lenArr = arrRefreshEl.length,
	i;
	for (i=0;i<lenArr;i++) {
		var refreshScroll = jQuery(arrRefreshEl[i]).parents(".cusel").find(".cusel-scroll-wrap").eq(0);
		refreshScroll.find(".cusel-scroll-pane").jScrollPaneRemoveCusel();
		refreshScroll.css({
			visibility: "hidden",
			display : "block"
		});
		var	arrSpan = refreshScroll.find("span"),
		defaultHeight = arrSpan.eq(0).outerHeight();
		if (arrSpan.length>params.visRows) {
			refreshScroll.css({
				height: defaultHeight*params.visRows+"px",
				display : "none",
				visibility: "visible"
			})
			.children(".cusel-scroll-pane").css({
				height: defaultHeight*params.visRows+"px"
			});
		}
		else {
			refreshScroll.css({
				display : "none",
				visibility: "visible"
			});
		}
	}
}

/*
-------------------
Binding with dom
-------------------
*/
var cuSelParams = {
	changedEl: ".selectStylized",
//	visRows: 7,
	scrollArrows: true
}
cuSel(cuSelParams);
