(function($) {
	/** dropdown
	  * parameters: options
	  *
	  * configure a dropdown, options outlined below
	*/
	
	$.fn.dropdown = function(options) {
		// default options
		var options = $.extend({
			// selector for holder itmes, triggers and menus
			trigger: "> a:first",
			triggerType: 'click',
			menu: "> ul:first",
			// base zIndex of dropdown menus
			zIndex: 100,
			// secounds to avoid the flick when mouse entering, leaving
			timeout: 0.2,
			// CSS class name for opened menu and trigger
			openedClass: "opened",
			// vertical offset for dropdown menu (false: not set, function: evaluate it with this)
			topOffset: 0,
			// left offset for dropdown menu (false: not set, function: evaluate it with this)
			leftOffset: 0,
			// set menu elements to 'relative' in JS
			positioning: true,
			// adds a 'close' button, disables mouseover detection once opened
			close: true,
			closeTrigger: ".close:first",
			// close menu when any anchor inside menu is clicked
			closeByAnchorClick: true
		}, options || {});

		/** getDimensions
		  * parameters: none
		  *
		  * returns an array with height, width dimensions of the browser
		*/
		
		function getDimensions() {
			var el = $(window);
			// fix a jQuery/Opera bug with determining the window height
			var h = $.browser.opera && $.browser.version > '9.5' && $.fn.jquery <= '1.2.6' ?
				document.documentElement['clientHeight'] : 
				el.height();
			return [h, el.width()];
		}

		$(this).each(function() {
			var item = $(this), trigger, menu;
			if(options.trigger) {
				trigger = item.find(options.trigger);
				menu = item.find(options.menu);
			} else {
				menu = item;
			}

			var open, close;
			var timeout;
			var overlay, resize;

			open = function() {
        (!jQuery.browser.mozilla) ? bSelectOpened = false : null;
				if(timeout) {
					clearTimeout(timeout);
					timeout = undefined;
				}

				if(menu.is(":hidden")) {
					if(!options.close) {
						var w = getDimensions();
						overlay = $("<div/>")
							.css({
								height: w[0],
								width: w[1],
								top: 0,
								left: 0,
								position: "fixed",
								zIndex: (options.zIndex - 1)
							})
							.click(function() {
								close(true);
							})
							.appendTo(trigger ? item : "body");
						resize = function() {
							var w = getDimensions();
							overlay.css({
								height: w[0],
								width: w[1]
							});
						};
						$(window).bind("resize", resize);
					}

					if(trigger) {
						trigger.addClass(options.openedClass)
							.bind("mouseenter", open)
							.bind("mouseleave", close);
					}
					menu.addClass(options.openedClass);
					if(!(jQuery.browser.msie && jQuery.browser.version < 7 && trigger && menu.parent().is("body"))) {
						$.each([["left", 0], ["top", trigger ? trigger.height() : 0]], function() {
							var option = options[this[0] + "Offset"];
							if(option == "center") option = function(menu, trigger){ return -((menu.width() - (Number(trigger.width() )+Number( trigger.css('padding-left').toString().replace('px',''))+Number( trigger.css('padding-right').toString().replace('px','')) )) / 2); };
							if($.isFunction(option)) {
								menu.css(this[0], option.call(item, menu, trigger) + this[1] + "px");
							} else if (!(typeof option == 'boolean' && !option)) {
								menu.css(this[0], option + this[1] + "px");
							}
						});
						menu.css("zIndex", options.zIndex);
					}
					menu.bind("mouseenter", open)
						.bind("mouseleave", close);

					if(jQuery.browser.msie && jQuery.browser.version < 7 && trigger && !menu.parent().is("body")) {
						menu.show();
						var offset = menu.offset();
						menu.hide();
						menu.appendTo("body")
							.css("position", "absolute")
							.css("left", offset.left)
							.css("top", offset.top);
					}
					menu.animate({opacity: "show"}, 300);

					if(options.onopen) {
						options.onopen.call(menu, trigger);
					}
				}

				return false;
			};
			close = function(immediate) {
        if ( ((!jQuery.browser.msie) && (!jQuery.browser.safari)) || (!bSelectOpened) ) {
  				if(menu.is(":visible")) {
  					var f = function() {
  						if(!options.close) {
  							$(window).unbind("resize", resize);
  							overlay.remove();
  						}
  
  						if(trigger) {
  							trigger.removeClass(options.openedClass)
  								.unbind("mouseenter", open)
  								.unbind("mouseleave", close);
  						}
  						menu.removeClass(options.openedClass)
  							.unbind("mouseenter", open)
  							.unbind("mouseleave", close)
  							.animate({opacity: "hide"}, 100);
  
  						if(options.onclose) {
  							options.onclose.call(menu, trigger);
  						}
  					};
  					if(typeof immediate == 'boolean' && immediate) {
  						f();
  					} else if(options.close) {
  						// disable timeout if in 'close' mode
  						timeout = setTimeout(f, options.timeout * 2000);
  					}
  				}
        }
				return false;
			};

			item.bind("open", open);
			item.bind("close", function() {
				close(true);
			});


      if(options.positioning && item.css("position") == "static") {
				item.css("position", "relative");
			}
			menu
				.css({display: "none", position: "absolute"})
        .find((options.closeByAnchorClick ? "a," : "") + options.closeTrigger)
					.click(function() {
						close(true);
					});

      var bSelectOpened = false;
      if (!jQuery.browser.mozilla) {
    //   menu.find("select").click( function() {
     //       bSelectOpened = true;
  	//				clearTimeout(timeout);
  	//				timeout = undefined;
     //     });
      }
      
			if(trigger) {
				switch(options.triggerType){
					case 'mouseover':
					case 'hover':
						trigger.mouseover(open);
						break;
					case 'click':
						trigger.click(open);
				}
				
			}
		});

		return $(this);
	};
})(jQuery);
