/**
 * @author Alexander Farkas
 * @ version 1.05
 */
(function($){
	
	function getFnIndex(args){
		var ret = 2;
		$.each(args, function(i, data){
			
			if($.isFunction(data)){
				ret = i;
				return false;
			}
		});
		return ret;
	}
	
	
(function(){
	
	var contains = document.compareDocumentPosition ?  function(a, b){
		return a.compareDocumentPosition(b) & 16;
	} : function(a, b){
		return a !== b && (a.contains ? a.contains(b) : true);
	},
	oldLive = $.fn.live,
	oldDie = $.fn.die;
	
	function createEnterLeaveFn(fn, type){
		return jQuery.event.proxy(fn, function(e) {
			if( this !== e.relatedTarget && e.relatedTarget && !contains(this, e.relatedTarget) ){
				e.type = type;
				fn.apply(this, arguments);
			}
		});
	}
	
	var enterLeaveTypes = {
		mouseenter: 'mouseover',
		mouseleave: 'mouseout'
	};
	
	$.fn.live = function(types){
		var that 	= this,
			args 	= arguments,
			fnIndex 	= getFnIndex(args),
			fn 		= args[fnIndex];
		
		$.each(types.split(' '), function(i, type){
			var proxy = fn;
			
			if(enterLeaveTypes[type]){
				proxy = createEnterLeaveFn(proxy, type);
				type = enterLeaveTypes[type];
			}
			args[0] = type;
			args[fnIndex] = proxy;
			oldLive.apply(that, args);
		});
		return this;
	};
	
	$.fn.die = function(type, fn){
		if(/mouseenter|mouseleave/.test(type)){
			if(type == 'mouseenter'){
				type = type.replace(/mouseenter/g, 'mouseover');
			} 
			if(type == 'mouseleave') {
				type = type.replace(/mouseleave/g, 'mouseout');
			}
		}
		oldDie.call(this, type, fn);
		return this;
	};
	
	
	function createBubbleFn(fn, selector, context){
		return jQuery.event.proxy(fn, function(e) {
			var parent = this.parentNode,
				stop 	= (enterLeaveTypes[e.type]) ? e.relatedTarget : undefined;
			fn.apply(this, arguments);
			while(parent && parent !== context && parent !== e.relatedTarget){
				if($.multiFilter( selector, [parent] )[0]){
					fn.apply(parent, arguments);
				}
				parent = parent.parentNode;
			}
		});
	}
	
	$.fn.bubbleLive = function(){
		var args 	= arguments,
			fnIndex = getFnIndex(args);
		
		args[fnIndex] = createBubbleFn(args[fnIndex], this.selector, this.context);
		$.fn.live.apply(this, args);
	};
	
	$.fn.liveHover = function(enter, out){
		return this.live('mouseenter', enter)
					.live('mouseleave', out);
	};
})();



(function(){
	
	$.support.bubblingChange = !($.browser.msie || $.browser.safari);
	
	if(!$.support.bubblingChange){
	
	var oldLive = $.fn.live,
		oldDie = $.fn.die;
	
	function detectChange(fn){
		return $.event.proxy(fn, function(e){
			var jElm = $(e.target);
			if ((e.type !== 'keydown' || e.keyCode === 13) && jElm.is('input, textarea, select')) {
				
				var oldData 			= jElm.data('changeVal'), 
					isRadioCheckbox 	= jElm.is(':checkbox, :radio'),
					nowData;
				if(isRadioCheckbox && jElm.is(':enabled') && e.type === 'click'){
					nowData = jElm.is(':checked');
					if((e.target.type !== 'radio' || nowData === true) && e.type !== 'change' && oldData !== nowData){
						e.type = 'change';
						jElm.trigger(e);
					}
				} else if (!isRadioCheckbox) {
					nowData = jElm.val();
					if(oldData !== undefined && oldData !== nowData){
						e.type = 'change';
						jElm.trigger(e);
					}
				}
				if(nowData !== undefined){
					jElm.data('changeVal', nowData);
				}
			}
		});
	}
	
	function createChangeProxy(fn){
		return $.event.proxy(fn, function(e){
			if(e.type === 'change'){
				var jElm 	= $(e.target),
					nowData = (jElm.is(':checkbox, :radio')) ? jElm.is(':checked') : jElm.val();
				if(nowData === jElm.data('changeVal')){
					return false;
				}
				jElm.data('changeVal', nowData);
			}
			fn.apply(this, arguments);
		});
	}
	
	$.fn.live = function(type, fn){
		var that 	= this,
			args 	= arguments,
			fnIndex	= getFnIndex(args),
			proxy 	= args[fnIndex];
			
		if(type.indexOf('change') != -1){
			$(this.context)
				.bind('click focusin focusout keydown', detectChange(proxy));
			proxy = createChangeProxy(proxy);
		}
		args[fnIndex] = proxy;
		oldLive.apply(that, args);
		return this;
	};
	$.fn.die = function(type, fn){
		if(type.indexOf('change') != -1){
			$(this.context)
				.unbind('click focusin focusout keydown', fn);
		}
		oldDie.apply(this, arguments);
		return this;
	};
	
	}
})();

/**
 * Copyright (c) 2007 Jörn Zaefferer
 */


(function(){
	$.support.focusInOut = !!($.browser.msie);
	if (!$.support.focusInOut) {
		$.each({
			focus: 'focusin',
			blur: 'focusout'
		}, function(original, fix){
			$.event.special[fix] = {
				setup: function(){
					if (!this.addEventListener) {
						return false;
					}
					this.addEventListener(original, $.event.special[fix].handler, true);
				},
				teardown: function(){
					if (!this.removeEventListener) {
						return false;
					}
					this.removeEventListener(original, $.event.special[fix].handler, true);
				},
				handler: function(e){
					arguments[0] = $.event.fix(e);
					arguments[0].type = fix;
					return $.event.handle.apply(this, arguments);
				}
			};
		});
	}
	//IE has some troubble with focusout with select and keyboard navigation
	var activeFocus = null, block;
	
	$(document)
		.bind('focusin', function(e){
			var target = e.realTarget || e.target;
			if (activeFocus && activeFocus !== target) {
				e.type = 'focusout';
				$(activeFocus).trigger(e);
				e.type = 'focusin';
				e.target = target;
			}
			activeFocus = target;
		})
		.bind('focusout', function(e){
			activeFocus = null;
		});
		
})();
})(jQuery);
