
/***************************************************************************

	sexy-combo 2.1.3	: A jQuery date time picker.
	
	Authors: 
		Kadalashvili.Vladimir@gmail.com - Vladimir Kadalashvili
		thetoolman@gmail.com 
		
	Version: 2.1.3
	
	Website: http://code.google.com/p/sexy-combo/
	

 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 ***************************************************************************/


;(function($) {
    $.fn.ScoachDropDown = function(config) {
        return this.each(function() {
		if ("SELECT" != this.tagName.toUpperCase()) {
		    return;	
		}
	    new $sc(this, config);
	    });  
    };
	
    $.fn.ScoachListBox = function(config) {
        return this.each(function() {
		if ("SELECT" != this.tagName.toUpperCase()) {
		    return;	
		}
	    new $sc(this, config, true);
	    });  
    };
    
    //default config options
    var defaults = {
        //skin name
        skin: "default",
	
	    //this suffix will be appended to the selectbox's name and will be text input's name
	    suffix: "$ComboBox",
	
	    //the same as the previous, but for hidden input
	    hiddenSuffix: "$ComboHidden",
	    
	    //rename original select, and call the hidden field the original name attribute?
	    renameOriginal: false,
	    
	   //initial / default hidden field value.
	   //Also applied when user types something that is not in the options list
	    initialHiddenValue: "",
	
	    //if provided, will be the value of the text input when it has no value and focus
	    emptyText: "",
	
	    //if true, autofilling will be enabled
	    autoFill: false,
	
	    //if true, selected option of the selectbox will be the initial value of the combo
	    triggerSelected: true,
		
	    //if true, the options list will be placed above text input
	    dropUp: false,
	
	    //separator for values of multiple combos
	    separator: ",",
			
		//key json name for key/value pair
		key: "value",
		
		//value json for key/value pair
		value: "text",

	    //all callback functions are called in the scope of the current sexyCombo instance
	
	    //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,
	    
		checkWidth: true
    };
    
    //constructor
    //creates initial markup and does some initialization
    $.sexyCombo = function(selectbox, config, isListBox) {
		//alert('new');
        if (selectbox.tagName.toUpperCase() != "SELECT")
	        return;
		
		// No reload Sexybox if partial postbacks
		if ($(selectbox).hasClass('Loaded')) {
			return;
		}
		$(selectbox).addClass('Loaded');
			    
	    this.config = $.extend({}, defaults, config || {}); 
		this.IsListBox = isListBox;
	    
	    this.selectbox = $(selectbox);
	    this.wrapper = this.selectbox.parent();
		this.options = this.selectbox.children().filter("option");
			
		if (!this.IsListBox) {
			this.input = this.wrapper.children('div.SelectBox');
			if (this.input.length == 0) {
				this.input = $("<div />").
				appendTo(this.wrapper).
				addClass("SelectBox").
				attr("name", this.selectbox.attr("name") + this.config.suffix);
			}
		}
	    
	    var origName = this.selectbox.attr("name");
	    var newName = origName + this.config.hiddenSuffix;
	    if(this.config.renameOriginal) { 
	    	this.selectbox.attr("name", newName);
	    }
	    
		if (!this.IsListBox) {
			this.hidden = this.wrapper.children('input:hidden');
			if (this.hidden.length == 0) {
				this.hidden = $("<input type='hidden' />").
				appendTo(this.wrapper).
				attr("value", this.config.initialHiddenValue).
				attr("id", this.config.renameOriginal ? origName : newName);
			}
			
			this.icon = this.wrapper.children('div.icon');
			if (this.icon.length == 0) {
				this.icon = $("<div />").
				appendTo(this.wrapper).
				addClass("icon"); 
			}
		}
	
	    this.listWrapper = this.wrapper.children('div.list-wrapper');
		this.scrollbar = this.listWrapper.children('div.scrollbar');
		
		this.scrollbar_top = this.scrollbar.children('div.scrollbar_top');
		this.scrollbar_top.mousedown(function(e) {
			self.moveUpInterval = setInterval( function() {
				self.moveUpIntervalIsActive = true;
				self.moveUp(self); 
			}, 100);
	    });
		this.scrollbar_top.mouseup(function(e) {
			if (!self.moveUpIntervalIsActive) {
				self.moveUp(self);
			}
			clearInterval(self.moveUpInterval);
			self.moveUpIntervalIsActive = false;
	    });
		
		this.scrollbar_middle = this.scrollbar.children('div.scrollbar_middle');
		this.scrollbar_block = this.scrollbar_middle.children('div.scrollbar_block');
		this.scrollbar_block.draggable({ 
			containment: 'parent', 
			drag: function(event, ui) {
				var pos = $(this).position();
				var middleHeight = self.scrollbar_middle.height()-40;
				var itemsHeight = self.getListItemsHeight() - self.getListMaxHeight();
				var newPos = (((pos.top-15) * 100.0 / middleHeight) * itemsHeight / 100.0);
				self.list.css('top', -newPos + "px");
			}
		});

		this.scrollbar_bottom = this.scrollbar.children('div.scrollbar_bottom');
		this.scrollbar_bottom.mousedown(function(e) {
			self.moveDownInterval = setInterval( function() {
				self.moveDownIntervalIsActive = true;
				self.moveDown(self); 
			}, 100);
	    });
		this.scrollbar_bottom.mouseup(function(e) {
			if (!self.moveDownIntervalIsActive) {
				self.moveDown(self);
			}
			clearInterval(self.moveDownInterval);
			self.moveDownIntervalIsActive = false;
	    });
		
	    this.updateDrop();
	
	    this.list = this.listWrapper.children('ul');
	    var self = this;
		var optWidths = [];
	    this.options.each(function() {					   
	        var optionText = $.trim($(this).text());
			var optionValue = $.trim($(this).val());
			if (self.config.checkWidth) {
			    optWidths.push($("<li />").
	            appendTo(self.list).
	            html("<span class='" + optionValue + "'>" + optionText + "</span>").
	            addClass("visible").find("span").outerWidth());	
			}
			else {
	            $("<li />").
	            appendTo(self.list).
	            html("<span>" + optionText + "</span>").
	            addClass("visible");
			}
	    });  
		
	    this.listItems = this.list.children();		
		
		if (optWidths.length) {
		    optWidths = optWidths.sort(function(a, b) {
		        return a - b;									
		    });
		    var maxOptionWidth = optWidths[optWidths.length - 1];
		}

        this.singleItemHeight = this.listItems.outerHeight();
		if (!this.IsListBox) {
			this.listWrapper.addClass("invisible");
		}
       
	    if ($.browser.opera) {
	        this.wrapper.css({position: "relative", left: "0", top: "0"});
	    } 
	
	    this.lastKey = null;
	    var self = this;
	
	    this.wrapper.data("sc:lastEvent", "click");
	
	    this.overflowCSS = "overflowY";
	
	    if ((this.config.checkWidth) && (this.listWrapper.innerWidth() < maxOptionWidth)) {
		    this.overflowCSS = "overflow";	
			
		}
        
	    this.notify("init");
	    this.initEvents();
		
		if (this.IsListBox) {
			this.highlightSelectedAll();
		}
		
		this.resizeHeight();
		
		this.setOverflow();
		
		// Scroll with MouseWhell only if Scrollbar
		if (this.ScrollBar) {
			this.list.mousewheel(function(event, delta) {
				if (delta > 0) {
					self.moveUp(self);
				} else {
					self.moveDown(self);
				}
				return false;
			});
		}
    };
    
    //shortcuts
    var $sc = $.sexyCombo;
    $sc.fn = $sc.prototype = {};
    $sc.fn.extend = $sc.extend = $.extend;
    
    $sc.fn.extend({
        //TOC of our plugin
	    //initializes all event listeners
        initEvents: function() {
	        var self = this;
			if (this.wrapper.data('eventsbound') == true)
				return;
			this.wrapper.data('eventsbound', true);
			
			if (!this.IsListBox) {
				this.wrapper.bind("click", function(e) {
					if (!self.wrapper.data("sc:positionY"))	{
						self.wrapper.data("sc:positionY", e.pageY);	    	
					}
					self.wrapper.data("sc:lastEvent", "click");
					self.iconClick(e);	
				});
				
				$(document).keypress(function(e) {
					if (self.isListOpen) {
						self.prepareKeyUp(self, e);
					}
				});
				
			}
			
			this.listItems.bind("mouseover", function(e) {
					//self.highlight(e.target);
					if ("LI" == e.target.nodeName.toUpperCase()) {
						self.highlight(e.target);	
					}
					else {
						self.highlight($(e.target).parent());	
					}
				});
	    
	        this.listItems.bind("click", function(e) {
	            self.listItemClick($(e.target));
	        });
	        
			this.listItems.bind("dblclick", function(e) {
				self.listItemDoubleClick($(e.target));
			});

		
			// hide dropdown list if outside click dropdown
			if (!self.IsListBox) {
				$(document).bind("click", function(e) {
					if ((self.icon.get(0) == e.target) 
					|| (self.wrapper.get(0) == e.target) 
					|| (self.input.get(0) == e.target)
					|| (self.scrollbar.get(0) == e.target)
					|| (self.scrollbar_top.get(0) == e.target)
					|| (self.scrollbar_middle.get(0) == e.target)
					|| (self.scrollbar_bottom.get(0) == e.target)
					|| (self.scrollbar_block.get(0) == e.target))
						return;

					self.hideList();    
				});
			}
	    
	        this.triggerSelected();
	        this.applyEmptyText();
			
			//here
	        this.wrapper.bind("click", function() {
	            self.wrapper.data("sc:lastEvent", "click");								
	        });
		
			this.notify("initEvents");
	    },
	
	    getTextValue: function() {
            return this.__getValue("input");
	    },
	
	    getCurrentTextValue: function() {
            return this.__getCurrentValue("input");
	    },
	
	    getHiddenValue: function() {
            return this.__getValue("hidden");
	    },
	
	    getCurrentHiddenValue: function() {	    
	        return this.__getCurrentValue("hidden");
	    },
	
	    __getValue: function(prop) {
	        prop = this[prop];
	        if (!this.IsListBox)
	            return $.trim(prop.text());
		
	        var tmpVals = prop.text().split(this.config.separator);
	        var vals = [];
	    
	        for (var i = 0, len = tmpVals.length; i < len; ++i) {
	            vals.push($.trim(tmpVals[i]));
	        }	
	    
	        vals = $sc.normalizeArray(vals);
	    
	        return vals;
	    },
	
	    __getCurrentValue: function(prop) {
	        prop = this[prop];
	        if (!this.multiple)
	            return $.trim(prop.text());
		 
            return $.trim(prop.text().split(this.config.separator).pop());		 
	    },
	
	    //icon click event listener
	    iconClick: function(e) {
			if ((this.scrollbar.get(0) == e.target)
				|| (this.scrollbar_top.get(0) == e.target)
				|| (this.scrollbar_middle.get(0) == e.target)
				|| (this.scrollbar_bottom.get(0) == e.target)
				|| (this.scrollbar_block.get(0) == e.target)) {
				return;
			}
	        if (this.listVisible()) { 
	            this.hideList();
		    }
	        else {			
	            this.showList();	
		    }          
	    },
	
	    //returns true when dropdown list is visible
	    listVisible: function() {
	        return this.listWrapper.hasClass("visible");
	    },
	
		resizeHeight: function() {
			if (this.IsListBox) {
				var itemHeight = this.singleItemHeight;
				var selectHeight = this.selectbox.attr('size');
				this.boxHeight = itemHeight * selectHeight;
				this.wrapper.css('height', this.boxHeight + 'px');
				this.listWrapper.css('height', this.boxHeight + 'px');
				this.scrollbar.css('height', this.boxHeight + 'px');
				this.scrollbar_middle.css('height', (this.boxHeight-30) + 'px');
			} else {
				this.boxHeight = 200;
			}
		},
	
	    //shows dropdown list
	    showList: function() {
			this.isListOpen = true;
			this.wrapper.addClass("comboActive");
	        if (!this.listItems.filter(".visible").length)
	            return;

	        this.listWrapper.removeClass("invisible").
	        addClass("visible");
	        this.setListHeight();
		
		    var listHeight = this.listWrapper.height();
		    var inputHeight = this.wrapper.height();
		
		    var bottomPos = parseInt(this.wrapper.data("sc:positionY")) + inputHeight + listHeight;
		    var maxShown = $(window).height() + $(document).scrollTop();
		    if (bottomPos > maxShown) {
		        this.setDropUp(true); 
		    }
		    else {
		        this.setDropUp(false);	
		    }
		
		    if ("" != $.trim(this.input.text())) {
			    this.highlightSelected();	
			}
			this.wrapper.css("zIndex", "9999");	
			this.listWrapper.css("zIndex", "3000");
	        this.notify("showList");
	    },
	
	    //hides dropdown list
	    hideList: function() {
			this.isListOpen = false;
			this.wrapper.removeClass("comboActive");
	        if (this.listWrapper.hasClass("invisible"))
	            return;
	        this.listWrapper.removeClass("visible").
	        addClass("invisible");
	        this.listWrapper.css("zIndex", "1");	
			this.wrapper.css("zIndex", "1");	
	        this.notify("hideList");
	    },
	
	    //returns sum of all visible items height
	    getListItemsHeight: function() {
	       
			var itemHeight = this.singleItemHeight;
	        return itemHeight * 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();
			this.ScrollBar = true;
	        if (this.getListItemsHeight() <= maxHeight) {
				this.scrollbar.css('display', 'none');
				this.listWrapper.addClass('NoScrollBar');
				this.ScrollBar = false;
			} else {
				if (!this.IsListBox) {
					this.list.css('width', this.wrapper.width()-20 + "px");
				} else {
					this.list.css('width', this.wrapper.width()-21 + "px");
				}
			}
	    },
	
	    //highlights active item of the dropdown list
	    highlight: function(activeItem) {	
	        this.listItems.removeClass("hover");   
	        $(activeItem).addClass("hover");
	    },
		
	    //sets text and hidden inputs value
	    setComboValue: function(item, pop, hideList, init) {
	        var val = "";
			
			// Get Data from selected Item
			if (!this.IsListBox) {
				val = item.text();
			} else {
				if (item.children().size() > 0) {
					var childSpan = item.children("span");
					val = childSpan.attr("class");
				} else {
					val = item.attr("class");
				}
			}
			
			// Put Data to original Select Box 
	        if (this.IsListBox) {
				var selectItem = this.selectbox.children("option[value='"+val+"']");
				
				if (selectItem.attr('selected')) {
					selectItem.removeAttr('selected');
					item.parent().removeClass('active');
				} else {
					selectItem.attr('selected', 'selected');
					item.parent().addClass('active');
				}
	        } else {
	            val = $.trim(val);
				this.setHiddenValue(val, init);
	        }
			

			
			if (!this.IsListBox) {
				var oldVal = this.input.text();
				this.input.text(val);
				this.input.removeClass("empty");
				
				if (hideList) {
					this.hideList();
				}
				
				if (this.input.text() != oldVal && !this.IsListBox) {
					this.notify("textChange");	
				}
			}
	    },
	

	    //sets hidden inputs value
	    //takes text input's value as a param
	    setHiddenValue: function(val, init) {
	        var set = false;
	        val = $.trim(val);
	        var oldVal = this.hidden.val();
	    	    
	        if (!this.IsListBox) {
	            for (var i = 0, len = this.options.length; i < len; ++i){
		            if (val == this.options.eq(i).text()) {
		                this.hidden.val(this.options.eq(i).val());
			            set = true;
			            break;
		            }
		        }
	        } else {
	            var comboVals = this.getHiddenValue();
		        var hiddenVals = [];
		        for (var i = 0, len = comboVals.length; i < len; ++i) {
		            for (var j = 0, len1 = this.options.length; j < len1; ++j) {
		                if (comboVals[i] == this.options.eq(j).text()) {
			                hiddenVals.push(this.options.eq(j).val());
			            }      
		            }
		        }
				
				
		
		        //if (hiddenVals.length) {
		        //    set = true;
		        //this.hidden.val(hiddenVals.join(this.config.separator));
				//}
			}
	    
			if (!this.IsListBox) {
				if (!set) {
					this.hidden.val(this.config.initialHiddenValue);
				}
				this.selectbox.val(this.hidden.val());
			}
			
			if (!init) {
				this.selectbox.trigger("change");
			}
		},
	
		isInDoubleClickPhase: false,
		lastClickedItem: null,

		listItemDoubleClick: function(item) {
			this.selectbox.dblclick();
		},

		listItemClick: function(item) {
			if (this.isInDoubleClickPhase)
			{
				if (item[0].className == this.lastClickedItem[0].className)
				{
					this.selectbox.dblclick();
					return;
				}
			}
			this.lastClickedItem = item;
			this.isInDoubleClickPhase = true;
			var theCombo = this;
			
			window.setTimeout(function() {
				theCombo.isInDoubleClickPhase = false;
			}, 1800);
			this.setComboValue(item, true, true); 
		},
			
		//just returns integer value of list wrapper's max-height property
		getListMaxHeight: function() {
			return this.boxHeight;
		},
	
		//corrects list wrapper's height depending on list items height
		setListHeight: function() {
		
			var liHeight = this.getListItemsHeight();
			
			var maxHeight = this.getListMaxHeight();
			
		
			var listHeight = this.listWrapper.height();
			if (liHeight < listHeight) {
				this.listWrapper.height(liHeight); 
				
				return liHeight;
			}
			else if (liHeight >= listHeight) {
				this.listWrapper.height(Math.min(maxHeight, liHeight));
				
				return Math.min(maxHeight, liHeight);
			}
					
		},
	
		//returns active element of the dropdown list
		getActive: function() {
			return this.listItems.filter(".active");
		},
	
		//returns (hovered) element of the dropdown list
		getHover: function() {
			return this.listItems.filter(".hover");
		},
	
		prepareKeyUp: function(object, e) {
			this.lastKey = e.keyCode;
			var k = $sc.KEY;
			switch (e.keyCode) {
				case k.TAB:
				case k.RETURN:
					this.setComboValue(this.getHover(), true, true);		    	
					break;
				case k.DOWN:
					object.highlightNext();
					break;
				case k.UP:
					object.highlightPrev();
					break;
				case k.ESC:
					object.hideList();
					break;
			}
			return false;
		},
	
		//returns number of currently visible list items
		liLen: function() {
			return this.listItems.filter(".visible").length;
		},
		
		//highlights first item of the dropdown list
		highlightFirst: function() {
			this.listItems.removeClass("active").filter(".visible:eq(0)").addClass("active");
		},
	
		highlightSelected: function() {
			this.listItems.removeClass("active");
			var val = $.trim(this.input.text());
			var object = this;
			this.listItems.each(function() {
				var $this = $(this);
				if ($this.text() == val) {
					$this.addClass("active");	
					object.scrollDown();
				}
			});
		},
	
		highlightSelectedAll: function() {
			//this.listItems.removeClass("active");
			var object = this;
			var listItems = this.listItems;
			this.options.each(function() {
				var $this = $(this);
				if ($this.attr("selected")) {
					var selectItem = listItems.children("span." + $this.val()).parent();
					selectItem.addClass("active");
				}
			});
		},
	
		//highlights list item before currently active item
		highlightPrev: function() {
			var $prev = this.getHover().prev();
			
			while ($prev.length && $prev.hasClass("invisible"))
				$prev = $prev.prev();
			
				if ($prev.length) {
				this.getHover().removeClass("hover");
			$prev.addClass("hover");
			this.scrollUp();
			}
		},
	
		//highlights item of the dropdown list next to the currently active item
		highlightNext: function() {
			var $next = this.getHover().next();
			
			while ($next.hasClass("invisible") && $next.length) {
				$next = $next.next();
			}
			
			if ($next.length) {
				this.listItems.removeClass("hover");
			$next.addClass("hover");
			this.scrollDown();
			}
		},
	
		//scrolls list wrapper up when needed
		scrollUp: function() {		
			var maxScroll = this.getHoverIndex() * this.listItems.outerHeight();
			if (maxScroll < (-this.list.position().top)) {
				this.list.css('top', -maxScroll + "px");
				
				var pos = this.scrollbar_block.position();
				var middleHeight = this.scrollbar_middle.height()-40;
				var itemsHeight = this.getListItemsHeight() - this.getListMaxHeight();
				var newPos = ((maxScroll*100/itemsHeight)*middleHeight/100);
				this.scrollbar_block.css('top', newPos + "px");
			}     
		},
	
		//scrolls list wrapper down when needed
		scrollDown: function(force) {
			var beforeActive = this.getHoverIndex() + 1;
			/*if ($.browser.opera)
				++beforeActive;*/
			
			var minScroll = this.listItems.outerHeight() * beforeActive - this.listWrapper.height();

			if ($.browser.msie)
				minScroll += beforeActive;
			if (minScroll > (-this.list.position().top)) {
				this.list.css('top', -minScroll + "px");
				
				var pos = this.scrollbar_block.position();
				var middleHeight = this.scrollbar_middle.height()-40;
				var itemsHeight = this.getListItemsHeight() - this.getListMaxHeight();
				var newPos = ((minScroll*100/itemsHeight)*middleHeight/100);
				this.scrollbar_block.css('top', newPos + "px");
			}
		},
	
		moveDown: function(object) {
			var moveSpeed = 1;
			var pos = object.scrollbar_block.position();
			
			var middleHeight = object.scrollbar_middle.height()-40;
			var itemsHeight = object.getListItemsHeight() - object.getListMaxHeight();
			
			if (pos.top -15 + moveSpeed <= middleHeight) {
				object.scrollbar_block.css('top', (pos.top -15 + moveSpeed) + "px");
			} else {
				object.scrollbar_block.css('top', middleHeight + "px");
			}
			pos = object.scrollbar_block.position(); 
			
			var newPos = (((pos.top-15) * 100.0 / middleHeight) * itemsHeight / 100.0);
			object.list.css('top', -newPos + "px");
		},
	
		moveUp: function(object) {
			var moveSpeed = 1;
			var pos = object.scrollbar_block.position();
			
			var middleHeight = object.scrollbar_middle.height()-40;
			var itemsHeight = object.getListItemsHeight() - object.getListMaxHeight();
			
			if (pos.top -15 - moveSpeed >= 0) {
				object.scrollbar_block.css('top', (pos.top -15 - moveSpeed) + "px");
			} else {
				object.scrollbar_block.css('top', 0 + "px");
			}
			pos = object.scrollbar_block.position(); 
			
			var newPos = (((pos.top-15) * 100.0 / middleHeight) * itemsHeight / 100.0);
			object.list.css('top', -newPos + "px");
		},
		
		//returns index of currently hover list item
		getHoverIndex: function() {
			return $.inArray(this.getHover().get(0), this.listItems.filter(".visible").get());
		},

		//emptyText stuff
		applyEmptyText: function() {
			if (!this.config.emptyText.length)
				return;
			
			var self = this;	
			this.input.bind("focus", function() {
					self.inputFocus();
			}).
			bind("blur", function() {
					self.inputBlur();
			});	
			
			if ("" == this.input.text()) {
				this.input.addClass("empty").text(this.config.emptyText);
			}
		},
	
		inputFocus: function() {
			if (this.input.hasClass("empty")) {
			this.input.removeClass("empty").
			text("");
			}
		},
	
		inputBlur: function() {
			if ("" == this.input.text()) {
			this.input.addClass("empty").
			text(this.config.emptyText);
			}
			
		},
	
		//triggerSelected stuff
		triggerSelected: function() {
			if (!this.config.triggerSelected)
				return;
			
			var self = this;	
			if (!this.IsListBox && this.input.text() == "") {
				this.options.each(function() {
					if ($(this).attr("selected")) {
						self.setComboValue($(this), false, true, true);
					}
				});	
				return;
			}
			
			if (!this.IsListBox) {
				self.setComboValue(this.options.eq(0), false, false, true);
			}
		},
			
		//for internal use
		updateDrop: function() {
			if (this.config.dropUp)
				this.listWrapper.addClass("list-wrapper-up");
			else 
				this.listWrapper.removeClass("list-wrapper-up");		
		},
	
		//updates dropUp config option
		setDropUp: function(drop) {
			this.config.dropUp = drop;   
			this.updateDrop(); 
		},
	
		notify: function(evt) {
			if (!$.isFunction(this.config[evt + "Callback"]))
				return;
			
			this.config[evt + "Callback"].call(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	
	},
	
	//for debugging
	log: function(msg) {
	    var $log = $("#log");
	    $log.html($log.html() + msg + "<br />");
	},
	
    createSelectbox: function(config) {
	    var $selectbox = $("<select />").
	    appendTo(config.container).
	    attr({name: config.name, id: config.id, size: "1"});
	    	    
	    var data = config.data;
	    var selected = false;
	    
	    for (var i = 0, len = data.length; i < len; ++i) {
	        selected = data[i].selected || false;
	        $("<option />").appendTo($selectbox).
			attr("value", data[i][config.key]).
			text(data[i][config.value]).
			attr("selected", selected);
	    }
	    
	    return $selectbox.get(0);
	},
	
	create: function(config) {
            var defaults = {
	        //the name of the selectbox
	        name: "",
		//the ID of the selectbox
		id: "",
		//data for the options
		/*
		This is an array of objects. The objects should contain the following properties:
		(string)value - the value of the <option>
		(string) text - text of the <option>
		(bool) selected - if set to true, "selected" attribute of this <option> will be set to true
		*/
		data: [],
		
		//if true, combo with multiple choice will be created
		multiple: false,
		
		//key json name for key/value pair
		key: "value",
		
		//value json for key/value pair
		value: "text",		
		
		//an element that will contain the widget
		container: $(document),
		//url that contains JSON object for options data
		//format is the same as in data config option
		//if passed, "data" config option will be ignored
		url: "",
		//params for AJAX request
		ajaxData: {}
	    };
	    config = $.extend({}, defaults, config || {});
	    
            if (config.url) {
	        return $.getJSON(config.url, config.ajaxData, function(data) {
		    delete config.url;
		    delete config.ajaxData;
		    config.data = data;
		    return $sc.create(config);
		});
	    }
	    
	    config.container = $(config.container);
	    
            var selectbox = $sc.createSelectbox(config);
	    return new $sc(selectbox, config);
	    
	},
	
	normalizeArray: function(arr) {
	    var result = [];
	    for (var i = 0, len =arr.length; i < len; ++i) {
	        if ("" == arr[i])
		    continue;
		    
		result.push(arr[i]);    
	    }
	    
	    return result;
	}
    });
})(jQuery); 





/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * Version: 3.0.2
 * 
 * Requires: 1.2.2+
 */

(function($) {

var types = ['DOMMouseScroll', 'mousewheel'];

$.event.special.mousewheel = {
	setup: function() {
		if ( this.addEventListener )
			for ( var i=types.length; i; )
				this.addEventListener( types[--i], handler, false );
		else
			this.onmousewheel = handler;
	},
	
	teardown: function() {
		if ( this.removeEventListener )
			for ( var i=types.length; i; )
				this.removeEventListener( types[--i], handler, false );
		else
			this.onmousewheel = null;
	}
};

$.fn.extend({
	mousewheel: function(fn) {
		return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
	},
	
	unmousewheel: function(fn) {
		return this.unbind("mousewheel", fn);
	}
});


function handler(event) {
	var args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true;
	
	event = $.event.fix(event || window.event);
	event.type = "mousewheel";
	
	if ( event.wheelDelta ) delta = event.wheelDelta/120;
	if ( event.detail     ) delta = -event.detail/3;
	
	// Add events and delta to the front of the arguments
	args.unshift(event, delta);

	return $.event.handle.apply(this, args);
}

})(jQuery);

