if(jQuery) (function($){
	
	function renderOption(id, option) {
		var html = '<label><input type="checkbox" name="' + id + '[]" value="' + option.value + '"';
		if (option.selected) {
			html += ' checked="checked"';
		}
		if (option.disabled) {
			html += ' disabled="disabled"';
		}		
		html += ' />' + option.text + '</label>';
		
		return html;
	}
	
	function renderOptions(id, options, o) {
		var html = "";
		
		for (var i=0;i<options.length;i++) {
			if (options[i].optgroup) {
				html += '<label class="ms-optGroup">';
				
				if (o.optGroupSelectable) {
					html += '<input type="checkbox" class="ms-optGroup" />' + options[i].optgroup;
				}
				else {
					html += options[i].optgroup;
				}
				
				html += '</label><div class="ms-optGroupContainer">';
				html += renderOptions(id, options[i].options, o);				
				html += '</div>';
			}
			else {
				html += renderOption(id, options[i]);
			}
		}
		
		return html;
	}
	
	function buildOptions(options) {
		var multiSelect = $(this);
		var multiSelectOptions = multiSelect.next('.ms-multiSelectOptions');
		var o = multiSelect.data("config");
		var callback = multiSelect.data("callback");

		multiSelectOptions.html("");
		var html = "";

		if ( o.selectAll) {
			html += '<label class="ms-selectAll"><input type="checkbox" class="ms-selectAll" />' + o.selectAllText + '</label>';
		}

		html += renderOptions(multiSelect.attr('id'), options, o);	
		multiSelectOptions.html(html);
		
		var initialWidth = multiSelectOptions.width();
		var hasScrollbar = false;
		
		if (multiSelectOptions.height() > o.listHeight) {
			multiSelectOptions.css("height", o.listHeight + 'px');
			hasScrollbar = true;
		} 
		else {
			multiSelectOptions.css("height", '');
		}
		
		var scrollbarWidth = hasScrollbar && (initialWidth == multiSelectOptions.width()) ? 17 : 0;

		// if((multiSelectOptions.width() + scrollbarWidth) < multiSelect.outerWidth()) {
			// multiSelectOptions.css("width", multiSelect.outerWidth() - 2/*border*/ + 'px');
		// } else {
			// multiSelectOptions.css("width", (multiSelectOptions.width() + scrollbarWidth) + 'px');
		// }
		
		//if ($.fn.bgiframe) multiSelect.next('.ms-multiSelectOptions').bgiframe({ width: multiSelectOptions.width(), height: multiSelectOptions.height() });

		if (o.selectAll) {
			multiSelectOptions.find('INPUT.ms-selectAll').click(function() {
				multiSelectOptions.find('INPUT:checkbox').attr('checked', $(this).attr('checked')).parent("LABEL").toggleClass('ms-checked', $(this).attr('checked'));
			});
		}
		
		if (o.optGroupSelectable) {
			multiSelectOptions.addClass('ms-optGroupHasCheckboxes');
			multiSelectOptions.find('INPUT.ms-optGroup').click( function() {
				$(this).parent().next().find('INPUT:checkbox').attr('checked', $(this).attr('checked')).parent("LABEL").toggleClass('ms-checked', $(this).attr('checked'));
			});
		}
		
		multiSelectOptions.find('INPUT:checkbox').click( function() {
			$(this).parent("LABEL").toggleClass('ms-checked', $(this).attr('checked'));
			
			updateSelected.call(multiSelect);
			multiSelect.focus();
			if ($(this).parent().parent().hasClass('ms-optGroupContainer')) {
				updateOptGroup.call(multiSelect, $(this).parent().parent().prev());
			}
			if (callback) {
				callback($(this));
			}
		});
		
		multiSelectOptions.each(function() {
			$(this).find('INPUT:checked').parent().addClass('ms-checked');
		});
		
		updateSelected.call(multiSelect);
		
		if (o.optGroupSelectable) {
			multiSelectOptions.find('LABEL.ms-optGroup').each( function() {
				updateOptGroup.call(multiSelect, $(this));
			});
		}
		
		multiSelectOptions.find('LABEL:has(INPUT)').hover(
			function() {
				$(this).parent().find('LABEL').removeClass('ms-hover');
				$(this).addClass('ms-hover');
			}, 
			function() {
				$(this).parent().find('LABEL').removeClass('ms-hover');
			}
		);
		
		multiSelect.keydown( function(e) {		
			var multiSelectOptions = $(this).next('.ms-multiSelectOptions');

			if( multiSelectOptions.css('visibility') != 'hidden' ) {
				if (e.keyCode == 9) {
					$(this).addClass('ms-focus').trigger('click'); // esc, left, right - hide
					$(this).focus().next(':input').focus();
					return true;
				}
				
				// ESC, Left, Right
				if( e.keyCode == 27 || e.keyCode == 37 || e.keyCode == 39 ) {
					$(this).addClass('ms-focus').trigger('click');
				}
				// Down || Up
				if( e.keyCode == 40 || e.keyCode == 38) {
					var allOptions = multiSelectOptions.find('LABEL');
					var oldHoverIndex = allOptions.index(allOptions.filter('.ms-hover'));
					var newHoverIndex = -1;
					
					if (oldHoverIndex < 0) {
						multiSelectOptions.find('LABEL:first').addClass('ms-hover');
					}
					else if (e.keyCode == 40 && oldHoverIndex < allOptions.length - 1) {
						newHoverIndex = oldHoverIndex + 1;
					}
					else if (e.keyCode == 38 && oldHoverIndex > 0) {
						newHoverIndex = oldHoverIndex - 1;
					}

					if (newHoverIndex >= 0) {
						$(allOptions.get(oldHoverIndex)).removeClass('ms-hover');
						$(allOptions.get(newHoverIndex)).addClass('ms-hover');

						adjustViewPort(multiSelectOptions);
					}
					
					return false;
				}

				// Enter, Space
				if (e.keyCode == 13 || e.keyCode == 32) {
					var selectedCheckbox = multiSelectOptions.find('LABEL.ms-hover INPUT:checkbox');					
					selectedCheckbox.attr('checked', !selectedCheckbox.attr('checked')).parent("LABEL").toggleClass('ms-checked', selectedCheckbox.attr('checked'));					
					if (selectedCheckbox.hasClass("ms-selectAll")) {
						multiSelectOptions.find('INPUT:checkbox').attr('checked', selectedCheckbox.attr('checked')).parent("LABEL").addClass('ms-checked').toggleClass('ms-checked', selectedCheckbox.attr('checked')); 
					}
					updateSelected.call(multiSelect);
					
					if (callback) callback($(this));
					
					return false;
				}

				if (e.keyCode >= 33 && e.keyCode <= 126) {
					var match = multiSelectOptions.find('LABEL:startsWith(' + String.fromCharCode(e.keyCode) + ')');
					var currentHoverIndex = match.index(match.filter('LABEL.ms-hover'));
					
					var afterHoverMatch = match.filter(function (index) {
						return index > currentHoverIndex;
					});

					match = (afterHoverMatch.length >= 1 ? afterHoverMatch : match).filter("LABEL:first");

					if (match.length == 1) {
						multiSelectOptions.find('LABEL.ms-hover').removeClass('ms-hover');								
						match.addClass('ms-hover');
						adjustViewPort(multiSelectOptions);
					}
				}
			} 
			else {
				if (e.keyCode == 38 || e.keyCode == 40 || e.keyCode == 13 || e.keyCode == 32) { //up, down, enter, space - show
					$(this).removeClass('ms-focus').trigger('click');
					multiSelectOptions.find('LABEL:first').addClass('ms-hover');
					return false;
				}
				//  Tab key
				if (e.keyCode == 9) {
					multiSelectOptions.next(':input').focus();
					return true;
				}
			}
			if (e.keyCode == 13) return false;
		});
	}
	
	function adjustViewPort(multiSelectOptions) {
		var selectionBottom = multiSelectOptions.find('LABEL.ms-hover').position().top + multiSelectOptions.find('LABEL.ms-hover').outerHeight();
		if (selectionBottom > multiSelectOptions.innerHeight()) {		
			multiSelectOptions.scrollTop(multiSelectOptions.scrollTop() + selectionBottom - multiSelectOptions.innerHeight());
		}		
		if (multiSelectOptions.find('LABEL.ms-hover').position().top < 0) {		
			multiSelectOptions.scrollTop(multiSelectOptions.scrollTop() + multiSelectOptions.find('LABEL.ms-hover').position().top);
		}
	}
	
	function updateOptGroup(optGroup) {
		var multiSelect = $(this);
		var o = multiSelect.data("config");
		
		if(o.optGroupSelectable) {
			var optGroupSelected = true;
			$(optGroup).next().find('INPUT:checkbox').each( function() {
				if (!$(this).attr('checked')) {
					optGroupSelected = false;
					return false;
				}
			});
			
			$(optGroup).find('INPUT.ms-optGroup').attr('checked', optGroupSelected).parent("LABEL").toggleClass('ms-checked', optGroupSelected);
		}
	}
	
	function updateSelected() {
		var multiSelect = $(this);
		var multiSelectOptions = multiSelect.next('.ms-multiSelectOptions');
		var o = multiSelect.data("config");
		
		var i = 0;
		var selectAll = true;
		var display = '';
		multiSelectOptions.find('INPUT:checkbox').not('.ms-selectAll, .ms-optGroup').each( function() {
			if ($(this).attr('checked') && ($(this).attr("disabled") != true)) {
				i++;
				display = display + $(this).parent().text() + ', ';
			}
			//else if ($(this).attr("disabled") != true) selectAll = false;
			else selectAll = false
		});
		
		display = display.replace(/\s*\,\s*$/,'');
		
		if (i == 0) {
			multiSelect.find("span").html( o.noneSelected );
		} 
		else {
			if (o.oneOrMoreSelected == '*') {
				multiSelect.find("span").html(display);
				multiSelect.attr("title", display );
			} 
			else {
				multiSelect.find("span").html(o.oneOrMoreSelected.replace('%', i));
			}
		}

		if (o.selectAll) {
			multiSelectOptions.find('INPUT.ms-selectAll').attr('checked', selectAll).parent("LABEL").toggleClass('ms-checked', selectAll);
		}
	}
	
	$.extend($.fn, {
		multiSelect: function(o, callback) {
			if (!o) o = {};
			if (o.selectAll == undefined) o.selectAll = true;
			if (o.selectAllText == undefined) o.selectAllText = "Összes kijelölése";
			if (o.noneSelected == undefined) o.noneSelected = '--Válasszon!--';
			if (o.oneOrMoreSelected == undefined) o.oneOrMoreSelected = '% kijelölve';
			if (o.optGroupSelectable == undefined) o.optGroupSelectable = false;
			if (o.listHeight == undefined) o.listHeight = 150;

			$(this).each( function() {
				var select = $(this);
				//if (select.attr("disabled") == true) return false;
				var classes = $(this).attr("class");
				var html = '<a href="javascript:;" class="ms-multiSelect '+classes+'"><span></span></a>';
				html += '<div class="ms-multiSelectOptions '+classes+'" style="position: absolute; z-index: 99999; visibility: hidden;"></div>';
				$(select).after(html);
				
				var multiSelect = $(select).next('.ms-multiSelect');
				var multiSelectOptions = multiSelect.next('.ms-multiSelectOptions');
				
				// if the select object had a width defined then match the new multilsect to it
				//multiSelect.find("span").css("width", $(select).width() + 'px');
				
				multiSelect.data("config", o);				
				multiSelect.data("callback", callback);
				
				var options = [];
				$(select).children().each(function() {
					if (this.tagName.toUpperCase() == 'OPTGROUP') {
						var suboptions = [];
						options.push({ optgroup: $(this).attr('label'), options: suboptions });
						
						$(this).children('OPTION').each(function() {
							if ($(this).val() != '') {
								suboptions.push({ text: $(this).html(), value: $(this).val(), selected: $(this).attr('selected') });
							}
						});
					}
					else if (this.tagName.toUpperCase() == 'OPTION') {
						if ($(this).val() != '') {
							options.push({ text: $(this).html(), value: $(this).val(), selected: $(this).attr('selected') });
						}
					}
				});
				
				$(select).remove();
				
				multiSelect.attr("id", $(select).attr("id"));
				
				buildOptions.call(multiSelect, options);

				multiSelect
					.hover(
						function() {
							$(this).addClass('ms-hover');
						}, 
						function() {
							$(this).removeClass('ms-hover');
						}
					)
					.click(function() {
						if ($(this).hasClass('ms-active')) {
							$(this).multiSelectOptionsHide();
						} 
							else {
							$(this).multiSelectOptionsShow();
						}
						return false;
					})
					.focus(function() {
						$(this).addClass('ms-focus');
					})
					.blur(function() {
						$(this).removeClass('ms-focus');
					})
				;
				
				$(document).click(function(event) {
					if (!($(event.target).parents().andSelf().is('.ms-multiSelectOptions'))) {
						multiSelect.multiSelectOptionsHide();
					}
				});
			});
		},
		
		multiSelectOptionsUpdate: function(options) {
			buildOptions.call($(this), options);
		},
		
		multiSelectOptionsHide: function() {
			$(this).removeClass('ms-active').removeClass('ms-hover').next('.ms-multiSelectOptions').css('visibility', 'hidden');
		},
		
		multiSelectOptionsShow: function() {
			var multiSelect = $(this);
			var multiSelectOptions = multiSelect.next('.ms-multiSelectOptions');
			var o = multiSelect.data("config");
		
			$('.ms-multiSelect').multiSelectOptionsHide();
			multiSelectOptions.find('LABEL').removeClass('ms-hover');
			multiSelect.addClass('ms-active').next('.ms-multiSelectOptions').css('visibility', 'visible');
			multiSelect.focus();
			
			multiSelect.next('.ms-multiSelectOptions').scrollTop(0);

			var offset = multiSelect.position();
			multiSelect.next('.ms-multiSelectOptions').css({ top:  offset.top + $(this).outerHeight() + 'px' });
			multiSelect.next('.ms-multiSelectOptions').css({ left: offset.left + 'px' });
		},
		
		selectedValuesString: function() {
			var selectedValues = "";
			$(this).next('.ms-multiSelectOptions').find('INPUT:checkbox:checked').not('.ms-optGroup, .ms-selectAll').each(function() {
				selectedValues += $(this).attr('value') + ",";
			});
			return selectedValues.replace(/\s*\,\s*$/,'');
		}		
	});
	
	$.expr[":"].startsWith = function(el, i, m) {
		var search = m[3];        
		if (!search) return false;
		return eval("/^[/s]*" + search + "/i").test($(el).text());
	};
	
})(jQuery);
