(function($){
	/* Little trick to remove event bubbling that causes events recursion */
	var CB = function(e)
	{
		if (!e) var e = window.event;
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
	};
	
	$.fn.button = function(options) {
		/* IE6 background flicker fix */
		try	{ document.execCommand('BackgroundImageCache', false, true);	} catch (e) {}
		
		/* Default settings */
		var settings = {
			cls: 'jquery-button',  /* button  */
			empty: 'images/none.png',  /* button  */
			default_idx: 0,
			hover_idx: 1,
			disabled_idx: -1,
			onclick_idx: -1,
			width: 16,
			height: 16
		};
		
		/* Processing settings */
		settings = $.extend(settings, options || {});
		
		/* Adds disable/enable events */
		var addEvents = function(object)
		{
			var disabled = object.disabled;
			var $object = $(object);
			
			if ( object.stateInterval )
				clearInterval(object.stateInterval);
			
			object.stateInterval = setInterval(
				function() 
				{
					if ( object.disabled != disabled )
						$object.trigger( (disabled = !!object.disabled) ? 'disable' : 'enable');
				}, 
				10 /* in miliseconds. Low numbers this can decrease performance on slow computers, high will increase responce time */
			);
			return $object;
		};
		//try { console.log(this); } catch(e) {}
		
		/* Wrapping all passed elements */
		return this.each(function() 
		{
			var btn = this; /* Reference to DOM Element*/
			var $btn = addEvents(btn); /* Adds custom events and returns, jQuery enclosed object */
			var clicked = false;
			/* Removing wrapper if already applied  */
			if (btn.wrapper) btn.wrapper.remove();
			
			/* Creating wrapper for button and assigning "hover" event */
			var height = settings.height;
			var src = $(this).attr('src');
			var default_pos = 0;
			var disabled_pos = 0;
			var onclick_pos = 0;
			var hover_pos = 0;
			
			if (settings.default_idx != -1)
			{
				default_pos = -height * settings.default_idx;
			}
			
			if (settings.disabled_idx != -1)
			{
				disabled_pos = -height * settings.disabled_idx;
			}
			if (settings.onclick_idx != -1)
			{
				onclick_pos = -height * settings.onclick_idx;
			}
			if (settings.hover_idx != -1)
			{
				hover_pos = -height * settings.hover_idx;
			}
			
			btn.wrapper = $('<span class="' + settings.cls + '"><span class="mark"><img src="' + settings.empty + '" width="' + settings.width + '" height="' + height + '" /></span></span>');
			btn.wrapperInner = btn.wrapper.children('span:eq(0)');
			btn.img = btn.wrapperInner.children('img:eq(0)');
			btn.img.css({'background-position': '0px ' + default_pos + 'px'});
			btn.wrapper.hover(
				function(e) {
					if (!btn.disabled)
					{
						if (!clicked)
						{
							btn.img.css({'background-position': '0px ' + hover_pos + 'px'});
						}
						else
						{
							btn.img.css({'background-position': '0px ' + onclick_pos + 'px'});
						}
					}
					CB(e);
					},
				function(e) {
					if (!btn.disabled)
						btn.img.css({'background-position': '0px ' + default_pos + 'px'});
					CB(e);
					}
			);
			
			btn.img.mousedown(
				function(e) {
					if (e.button != 0) return;
					if (!btn.disabled)
					{
						clicked = true;
						btn.img.css({'background-position': '0px ' + onclick_pos + 'px'});
					}
					CB(e);
				}
			).mouseup(
				function(e) {
					if (e.button != 0) return;
					if (!btn.disabled)
					{
						clicked = false;
						btn.img.css({'background-position': '0px ' + hover_pos + 'px'});
					}
					CB(e);
				}
			);
			
			/* Wrapping button */
			$btn.css({position: 'absolute', zIndex: -1, visibility: 'hidden'}).after(btn.wrapper);
			
			btn.wrapper.click(function(e) {
				if (!btn.disabled)
				{
					$btn.trigger('click',[e]);
				}
				CB(e);
				return false;
			});
			$btn.click(function(e) { CB(e); });
			
			if (settings.disabled_idx != -1)
			{
				$btn.bind('disable', function() { 
						btn.img.css({'background-position': '0px ' + disabled_pos + 'px'});
					}).bind('enable', function() {
						btn.img.css({'background-position': '0px ' + default_pos + 'px'});
					});
			}
			
			/* Disable image drag-n-drop for IE */
			btn.img.bind('dragstart', function () {return false;}).bind('mousedown', function () {return false;});
			btn.img.css({'background-image':'url(' + src + ')'})
			
			/* Firefox antiselection hack */
			if ( window.getSelection )
				btn.wrapper.css('MozUserSelect', 'none');
			
			/* Applying button state */
			if ( btn.disabled )
			{
				btn.img.css({'background-position': '0px ' + disabled_pos + 'px'});
			}
		});
	}
})(jQuery);
