/**
 * @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);
