zoukankan      html  css  js  c++  java
  • mass Framework event模块 v4

    event.js

    
    //==========================================
    //  事件模块(包括伪事件对象,事件绑定与事件代理)
    //==========================================
    $.define("event",document.dispatchEvent ?  "node" : "node,event_fix",function(){
        // $.log("已加载target模块")
        var rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,  rmapper = /(\w+)_(\w+)/g,
        rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, revent = /(^|_|:)([a-z])/g
        function addCallback(queue, obj){//添加回调包到列队中
            var check = true, fn = obj.callback;
            for ( var i = 0, el; el = queue[i++]; ) {
                if( el.callback === fn ){
                    check = false;
                    break;
                }
            }
            if( check ){
                queue.push(obj);
            }
        }
        function quickIs( elem, m ) {
            var attrs = elem.attributes || {};
            return (
                (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
                (!m[2] || (attrs.id || {}).value === m[2]) &&
                (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
                );
        }
        //如果不存在添加一个
        var facade = $.event = $.event || {};
        //添加或增强二级属性eventAdapter
        $.Object.merge(facade,{
            eventAdapter:{
                focus: {
                    delegateType: "focusin"
                },
                blur: {
                    delegateType: "focusout"
                },
                beforeunload: {
                    setup: function(src, _, _, fn ) {
                        // We only want to do this special case on windows
                        if ( $.type(src, "Window") ) {
                            src.onbeforeunload = fn;
                        }
                    },
                    teardown: function( src, _, _, fn ) {
                        if ( src.onbeforeunload === fn ) {
                            src.onbeforeunload = null;
                        }
                    }
                }
            }
        });
        var eventAdapter  = $.event.eventAdapter;
        $.mix(facade,{
            bind : function( hash ){
                //它将在原生事件派发器或任何能成为事件派发器的普通JS对象添加一个名叫uniqueNumber的属性,用于关联一个缓存体,
                //把需要的数据储存到里面,而现在我们就把一个叫events的对象储放都它里面,
                //而这个event的表将用来放置各种事件类型与对应的回调函数
                if(arguments.length > 1 ){
                    throw "$.event bind method only need one argument, and it's a hash!"
                }
                var target = this, DOM =  $[ "@target" ] in target, events = $._data( target),
                types = hash.type, fn = hash.callback,selector = hash.selector, callback;
                if(target.nodeType === 3 || target.nodeType === 8 || !events){
                    return
                }
                hash.uuid =  $.getUid(fn); //确保UUID,bag与callback的UUID一致
                if( DOM ){ //处理DOM事件
                    callback = events.callback ||  (events.callback = function( e ) {
                        return ((e || event).type !== facade.fireType ) ? facade.dispatch.apply( callback.target, arguments ) : void 0;
                    });
                    callback.target = target;
                    types = types.replace( rhoverHack, "mouseover$1 mouseout$1" )
                }
                events = events.events || (events.events = {});
                //对多个事件进行绑定
                types.replace( $.rword, function( old ){
                    var
                    tns = rtypenamespace.exec( old ) || [],//"focusin.aaa.bbb"
                    namespace = ( tns[2] || "" ).split( "." ).sort(),//取得命名空间 "aaa.bbb"
                    adapter = DOM && eventAdapter[ tns[1] ] || {},// focusin -> focus
                    type = (selector ? adapter.delegateType : adapter.bindType ) || tns[1],//focus
    
                    queue = events[ type ] = events[ type ] ||  [],  //创建事件队列
                    item = $.mix({
                        type: type,
                        origType: tns[1],
                        namespace: namespace.join(".")
                    }, hash, false);
                    //只有原生事件发送器才能进行DOM level2 多投事件绑定
                    if( DOM && !queue.length  ){
                        adapter = eventAdapter[ type ] || {};
                        if (!adapter.setup || adapter.setup( target, selector, item.origType, callback ) === false ) {
                            // 为此元素这种事件类型绑定一个全局的回调,用户的回调则在此回调中执行
                            $.bind(target, type, callback, !!selector)
                        }
                    }
               
                    addCallback( queue, item );//同一事件不能绑定重复回调
                });
                return this;
            },
            //外部的API已经确保typesr至少为空字符串
            unbind: function( hash, mappedTypes  ) {
                var target = this, events = $._data( target, "events");
                if(!events ) return;
                var types = hash.type || "", selector = hash.selector, fn = hash.callback,
                tns, type, origType, namespace, origCount, DOM =  $["@target"] in target,
                j, adapter, queue, item;
                //将types进行映射并转换为数组
                types = DOM ? types.replace( rhoverHack, "mouseover$1 mouseout$1" ) : types;
                types =  types.match( $.rword ) || [];
                for (var t = 0; t < types.length; t++ ) {
                    //"aaa.bbb.ccc" -> ["aaa.bbb.ccc", "aaa", "bbb.ccc"]
                    tns = rtypenamespace.exec( types[t] ) || []
                    origType = type = tns[1];
                    namespace = tns[2];
                    // 如果types只包含命名空间,则去掉所有拥有此命名空间的事件类型的回调
                    if ( !type  ) {
                        for ( j in events ) {
                            facade.unbind.call( target, {
                                type: j + types[t],//说明这个types[t]为命名空间
                                selector: selector,
                                callback: fn
                            }, true );
                        }
                        continue;
                    }
                    //如果使用事件冒充则找到其正确事件类型
                    adapter = eventAdapter[ type ] || {};
                    type = ( selector ? adapter.delegateType: adapter.bindType ) || type;
                    queue =  events[ type ] || [];
                    origCount = queue.length;
                    namespace = namespace ? new RegExp("(^|\\.)" + namespace.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
                    //  namespace =  namespace?  namespace.split( "." ).sort().join(".") : null;
                    //只有指定了命名空间,回调或选择器才能进入此分支
                    if ( fn || namespace || selector ) {
                        for ( j = 0; j < queue.length; j++ ) {
                            item = queue[ j ];
                            if ( ( mappedTypes || origType === item.origType ) &&
                                ( !fn || fn.uuid === item.uuid ) &&//如果指定了回调,只检测其UUID
                                ( !namespace || namespace.test( item.namespace ) ) &&//如果指定了命名空间
                                ( !selector || selector === item.selector || selector === "**" && item.selector ) ) {
                                queue.splice( j--, 1 );
                            }
                        }
                    } else {
                        //移除此类事件的所有回调
                        queue.length = 0;
                    }
                    if ( DOM && (queue.length === 0 && origCount !== queue.length) ) {//如果在回调队列的长度发生变化时才进行此分支
                        if ( !adapter.teardown || adapter.teardown( target, selector, origType, fn ) === false ) {
                            $.unbind( target, type, $._data( target, "callback") );
                        }
                        delete events[ type ];
                    }
                }
                if( $.isEmptyObject( events ) ){
                    fn = $.removeData( target,"callback") ;
                    fn.target = null;
                    $.removeData( target, "events") ;
                }
                return this;
            },
    
            fire: function( event ){//event的类型可能是字符串,原生事件对象,伪事件对象
                var target = this, namespace = [], type = event.type || event;
                if(!isFinite(event.mass)){
                    event = new jEvent(event);
                    if( ~type.indexOf( "." ) ) {//处理命名空间
                        namespace = type.split(".");
                        type = namespace.shift();
                        namespace.sort();
                        event.namespace = namespace.join( "." );
                        event.namespace_re = event.namespace ? new RegExp("(^|\\.)" + namespace.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
                    }
                    event.target = target;
                }
                var args = [ event ].concat( $.slice(arguments,1) );
                if( $["@target"] in target){
                    var cur = target,  ontype = "on" + type;
                    do{//模拟事件冒泡与执行内联事件
                        if( ($._data(cur,"events")|| {})[type] ){
                            facade.dispatch.apply( cur, args );
                        }
                        if (cur[ ontype ] && cur[ ontype ].call(cur) === false) {
                            event.preventDefault();
                        }
                        cur = cur.parentNode ||
                        cur.ownerDocument ||
                        cur === target.ownerDocument && window;
                    } while ( cur && !event.isPropagationStopped );
                    if ( !event.isDefaultPrevented ) {//模拟默认行为 click() submit() reset() focus() blur()
                        var old;//在opera 中节点与window都有document属性
                        if (ontype && target[ type ] && ((type !== "focus" && type !== "blur") || target.offsetWidth !== 0) && !target.eval) {
                            old = target[ ontype ];
                            if (old) {   // 不用再触发内联事件
                                target[ ontype ] = null;
                            }
                            facade.fireType = type;
                            target[ type ]();
                        }
                        delete facade.fireType ;
                        if ( old ) {
                            target[ ontype ] = old;
                        }
                    }
    
                }else{//普通对象的自定义事件
                    facade.dispatch.apply(target, args);
                }
                return this;
            },
            filter: function( cur, parent, expr ){
                var matcher = typeof expr === "function"? expr : expr.input ? quickIs : $.match
                for ( ; cur != parent; cur = cur.parentNode || parent ) {
                    if(matcher(cur, expr))
                        return true
                }
                return false;
            },
            dispatch: function( e ) {
                var win = ( this.ownerDocument || this.document || this ).parentWindow || window,
                event = facade.fix( e || win.event ),
                queue = $._data(this,"events");//这个其实是对象events
                if (  queue ) {
                    queue = queue[ event.type] || [];//到此处时才是数组
                    event.currentTarget = this;
                    var src = event.target,args = [event].concat($.slice(arguments,1)), result;
                    //复制数组以防影响下一次的操作
                    queue = queue.concat();
                    //开始进行拆包操作
                    for ( var i = 0, item; item = queue[i++]; ) {
                        //如果是事件代理,确保元素处于enabled状态,并且满足过滤条件
                        if ( !src.disabled && !(event.button && event.type === "click")
                            && (!item.selector  || facade.filter(src, this, item.selector))
                            && (!event.namespace || event.namespace_re.test( item.namespace ) ) ) {
                            //取得回调函数
                            event.type = item.origType;
                            result = item.callback.apply( item.selector ? src : this, args );
                            item.times--;
                            if(item.times === 0){
                                facade.unbind.call( this, item)
                            }
                            if ( result !== void 0 ) {
                                event.result = result;
                                if ( result === false ) {
                                    event.preventDefault();
                                    event.stopPropagation();
                                }
                            }
                            if ( event.isImmediatePropagationStopped ) {
                                break;
                            }
                        }
                    }
                }
    
                return event.result;
            },
            _dispatch: function( src, type, e ){
                e = facade.fix( e );
                e.type = type;
                for(var i in src){
                    if(src.hasOwnProperty(i)){
                        facade.dispatch.call( src[ i ], e );
                    }
                }
            },
            fix: function( event ){
                if( !isFinite(event.mass) ){
                    var originalEvent = event
                    event = new jEvent(originalEvent);
                    for( var prop in originalEvent ){
                        //去掉所有方法与常量
                        if( typeof originalEvent[prop] !== "function" && prop !== "type" ){
                            if(/^[A-Z_]+$/.test(prop))
                                continue
                            event[prop] = originalEvent[prop]
                        }
                    }
                    //如果不存在target属性,为它添加一个
                    if ( !event.target ) {
                        event.target = event.srcElement || document;
                    }
                    //safari的事件源对象可能为文本节点,应代入其父节点
                    if ( event.target.nodeType === 3 ) {
                        event.target = event.target.parentNode;
                    }
                    // 处理鼠标事件
                    if( /^(?:mouse|contextmenu)|click/.test(event.type) ){
                        //如果不存在pageX/Y则结合clientX/Y做一双出来
                        if ( event.pageX == null && event.clientX != null ) {
                            var doc = event.target.ownerDocument || document,
                            html = doc.documentElement, body = doc.body;
                            event.pageX = event.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html && html.clientLeft || body && body.clientLeft || 0);
                            event.pageY = event.clientY + (html && html.scrollTop  || body && body.scrollTop  || 0) - (html && html.clientTop  || body && body.clientTop  || 0);
                        }
                        //如果不存在relatedTarget属性,为它添加一个
                        if ( !event.relatedTarget && event.fromElement ) {
                            event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
                        }
                        //标准浏览判定按下鼠标哪个键,左1中2右3
                        var button = event.button
                        //IE event.button的意义
                        //0:没有键被按下 1:按下左键 2:按下右键 3:左键与右键同时被按下 4:按下中键 5:左键与中键同时被按下 6:中键与右键同时被按下 7:三个键同时被按下
                        if ( !event.which && isFinite(button) ) {
                            event.which  = [0,1,3,0,2,0,0,0][button];//0现在代表没有意义
                        }
                    }
                    if ( event.which == null ) {//处理键盘事件
                        event.which = event.charCode != null ? event.charCode : event.keyCode;
                    }
                    if( window.Touch && event.touches && event.touches[0] ){
                        $.log("fix touch pageXY")
                        event.pageX = event.touches[0].pageX
                        event.pageY = event.touches[0].pageY
                    }
                    //处理滚轮事件
                    if( event.type === "mousewheel" ){
                        if ("wheelDelta" in originalEvent){
                            var delta = originalEvent.wheelDelta/120;
                            //opera 9x系列的滚动方向与IE保持一致,10后修正
                            if(top.opera && opera.version() < 10)
                                delta = -delta;
                            event.wheelDelta = Math.round(delta); //修正safari的浮点 bug
                        }else if("detail" in originalEvent){
                            event.wheelDelta = -event.detail/3;
                        }
                    }
                    // 处理组合键
                    if ( event.metaKey === void 0 ) {
                        event.metaKey = event.ctrlKey;
                    }
                }
                return event;
            }
        });
    
        var jEvent = $.Event = function ( event ) {
            this.originalEvent = event.type ? event: {};
            this.type = (event.type || event).replace(/\..*/g,"");
            this.timeStamp  = Date.now();
            this.mass = $.mass;//用于判定是否为伪事件对象
        };
        // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
        jEvent.prototype = {
            constructor: jEvent,
            //http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/events.html#Conformance
            toString: function(){
                return "[object Event]"
            },
            preventDefault: function() {
                this.isDefaultPrevented = true;
                var e = this.originalEvent;
                // 如果存在preventDefault 那么就调用它
                if ( e.preventDefault ) {
                    e.preventDefault();
                }
                // 如果存在returnValue 那么就将它设为false
                e.returnValue = false;
                return this;
            },
            stopPropagation: function() {
                this.isPropagationStopped = true;
                var e = this.originalEvent;
                // 如果存在preventDefault 那么就调用它
                if ( e.stopPropagation ) {
                    e.stopPropagation();
                }
                // 如果存在returnValue 那么就将它设为true
                e.cancelBubble = true;
                return this;
            },
            stopImmediatePropagation: function() {
                this.isImmediatePropagationStopped = true;
                this.stopPropagation();
                return this;
            }
        };
        var types = "contextmenu,click,dblclick,mouseout,mouseover,mouseenter,mouseleave,mousemove,mousedown,mouseup,mousewheel," +
        "abort,error,load,unload,resize,scroll,change,input,select,reset,submit,input,"+"blur,focus,focusin,focusout,"+"keypress,keydown,keyup"
      
        //事件派发器的接口
        //实现了这些接口的对象将具有注册事件和广播事件的功能
        //http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
        $.EventTarget = {
            uniqueNumber : $.getUid({}),
            defineEvents : function( names ){
                var events = [];
                if(typeof names == "string"){
                    events = names.match( $.rword ) || [];
                }else if($.isArray(names)){
                    events = names;
                }
                events.forEach(function(name){
                    var method = 'on'+name.replace(revent,function($, $1, $2) {
                        return $2.toUpperCase();
                    });
                    if (!(method in this)) {
                        this[method] = function() {
                            return $.fn.on.apply(this, [].concat.apply([name], arguments));
                        };
                    }
                },this);
            }
        };
        "bind_on,unbind_off,fire_fire".replace( rmapper,function(_, type, mapper){
            $.EventTarget[ type ] = function(){
                $.fn[ mapper ].apply(this, arguments);
                return this;
            }
        });
        $.eventSupport = function( eventName,el ) {
            el = el || document.createElement("div");
            eventName = "on" + eventName;
            var ret = eventName in el;
            if ( el.setAttribute && !ret ) {
                el.setAttribute( eventName, "" );
                ret = typeof el[ eventName ] === "function";
                el.removeAttribute(eventName);
            }
            el = null;
            return ret;
        };
        /**
    用于在标准浏览器下模拟mouseenter与mouseleave
    现在除了IE系列支持mouseenter/mouseleave/focusin/focusout外
    opera11,FF10也支持这四个事件,同时它们也成为w3c DOM3 Event的规范
    详见http://www.filehippo.com/pl/download_opera/changelog/9476/
    http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
     */
        if( !+"\v1" || !$.eventSupport("mouseenter")){
            "mouseenter_mouseover,mouseleave_mouseout".replace(rmapper, function(_, type, mapper){
                eventAdapter[ type ]  = {
                    setup: function( src ){//使用事件冒充
                        $._data( src, type+"_handle", $.bind( src, mapper, function( e ){
                            var parent = e.relatedTarget;
                            try {
                                while ( parent && parent !== src ) {
                                    parent = parent.parentNode;
                                }
                                if ( parent !== src ) {
                                    facade._dispatch( [ src ], type, e );
                                }
                            } catch(err) { };
                        }));
                    },
                    teardown: function(){
                        $.unbind( this, mapper, $._data( type+"_handle" ) );
                    }
                };
            });
        }
        //在标准浏览器里面模拟focusin
        if( !$.eventSupport("focusin") ){
            "focusin_focus,focusout_blur".replace(rmapper, function(_,type, mapper){
                var notice = 0, focusinNotify = function (e) {
                    var src = e.target
                    do{//模拟冒泡
                        var events = $._data( src, "events" );
                        if(events && events[ type ]){
                            facade._dispatch( [ src ], type, e );
                        }
                    } while (src = src.parentNode );
                }
                eventAdapter[ type ] = {
                    setup: function( ) {
                        if ( notice++ === 0 ) {
                            document.addEventListener( mapper, focusinNotify, true );
                        }
                    },
                    teardown: function() {
                        if ( --notice === 0 ) {
                            document.removeEventListener( mapper, focusinNotify, true );
                        }
                    }
                };
            });
        }
        try{
            //FF需要用DOMMouseScroll事件模拟mousewheel事件
            document.createEvent("MouseScrollEvents");
            eventAdapter.mousewheel = {
                bindType    : "DOMMouseScroll",
                delegateType: "DOMMouseScroll"
            }
            try{
                //可能末来FF会支持标准的mousewheel事件,则需要删除此分支
                document.createEvent("WheelEvent");
                delete eventAdapter.mousewheel;
            }catch(e){};
        }catch(e){};
        //当一个元素,或者其内部任何一个元素获得焦点的时候会触发这个事件。
        //这跟focus事件区别在于,他可以在父元素上检测子元素获取焦点的情况。
        var  rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/
        function quickParse( selector ) {
            var quick = rquickIs.exec( selector );
            if ( quick ) {
                //   0  1    2   3
                // [ _, tag, id, class ]
                quick[1] = ( quick[1] || "" ).toLowerCase();
                quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
            }
            return quick;
        }
        "on_bind,off_unbind".replace( rmapper, function(_,method, mapper){
            $.fn[ method ] = function(types, selector, fn ){//$.fn.on $.fn.off
                if ( typeof types === "object" ) {
                    for ( var type in types ) {
                        $.fn[ method ].call(this, type, selector, types[ type ], fn );
                    }
                    return this;
                }
                var hash = {};
                for(var i = 0 ; i < arguments.length; i++ ){
                    var el = arguments[i];
                    if(typeof el == "number"){
                        hash.times = el
                    }else if(typeof el == "function"){
                        hash.callback = el
                    }if(typeof el === "string"){
                        if(hash.type != null){
                            hash.selector = el.trim()
                        }else{
                            hash.type = el.trim()
                        }
                    }
                }
                if(method === "on"){
                    if( !hash.type || !hash.callback ){//必须指定事件类型与回调
                        return this;
                    }
                    hash.times = hash.times > 0  ? hash.times : Infinity;
                    hash.selector =  hash.selector ? quickParse( hash.selector ) : false
                }
                if(this.mass && this.each){
                    return this.each(function() {
                        facade[ mapper ].call( this, hash );
                    });
                }else{
                    return facade[ mapper ].call( this, hash );
                }
            }
            $.fn[ mapper ] = function(){// $.fn.bind $.fn.unbind
                return $.fn[ method ].apply(this, arguments );
            }
        });
    
        $.implement({
            toggle: function(/*fn1,fn2,fn3*/){
                var fns = [].slice.call(arguments), i = 0;
                return this.click(function(e){
                    var fn  = fns[i++] || fns[i = 0, i++];
                    fn.call( this, e );
                })
            },
            hover: function( fnIn, fnOut ) {
                return this.mouseenter( fnIn ).mouseleave( fnOut || fnIn );
            },
            delegate: function( selector, types, fn, times ) {
                return this.on( types, selector, fn, times);
            },
            live: function( types, fn, times ) {
                $( this.ownerDocument ).on( types, this.selector, fn, times );
                return this;
            },
            one: function( types, fn ) {
                return this.on( types, fn, 1 );
            },
            undelegate: function(selector, types, fn ) {
                return arguments.length == 1? this.off( selector, "**" ) : this.off( types, fn, selector );
            },
            die: function( types, fn ) {
                $( this.ownerDocument ).off( types, fn, this.selector || "**", fn );
                return this;
            },
            fire: function(  ) {
                var args = arguments;
                if(this.mass && this.each){
                    return this.each(function() {
                        $.event.fire.apply(this, args );
                    });
                }else{
                    return $.event.fire.apply(this, args );
                }
            }
        });
    
        types.replace( $.rword, function( type ){
            $.fn[ type ] = function( callback ){
                return callback?  this.bind( type, callback ) : this.fire( type );
            }
        });
    });
    

    event_fix.js

    //=========================================
    //  事件补丁模块
    //==========================================
    $.define("event_fix", !!document.dispatchEvent, function(){
        //模拟IE678的reset,submit,change的事件代理
        var rform  = /^(?:textarea|input|select)$/i ,
        changeType = {
            "select-one": "selectedIndex",
            "select-multiple": "selectedIndex",
            "radio": "checked",
            "checkbox": "checked"
        }
        function changeNotify( e ){
            if( e.propertyName === ( changeType[ this.type ] || "value") ){
                $._data( this, "_just_changed", true );
                $.event._dispatch( $._data( this, "publisher" ), "change", e );
            }
        }
        function changeFire( e ){
            if( !$._data( this,"_just_changed" ) ){
                $.event._dispatch( $._data( this ,"publisher"), "change", e );
            }else{
                $.removeData( this, "_just_changed", true );
            }
        }
        function delegate( fn ){ 
            return function( src, selector, type ){
                var adapter = $.event.eventAdapter,
                fix = adapter[ type ] && adapter[ type ].check && adapter[ type ].check( src );
                return (fix || selector) ? fn(src, type, fix) : false;
            }
        }
    
        var facade = $.event = {
            eventAdapter:{
                //input事件的支持情况:IE9+,chrome+, gecko2+, opera10+,safari+
                input: {
                    check: function(src){
                        return rform.test(src.tagName) && !/^select/.test(src.type);
                    },
                    bindType: "change",
                    delegateType: "change"
                },
    
                change: {//change事件的冒泡情况 IE6-9全灭
                    check: function(src){
                        return rform.test(src.tagName) && /radio|checkbox/.test(src.type)
                    },
                    setup: delegate(function( src, type, fix ){
                        var subscriber = $._data( src, "subscriber", {} );//用于保存订阅者的UUID
                        $._data( src, "_beforeactivate", $.bind( src, "beforeactivate", function() {
                            var e = src.document.parentWindow.event, target = e.srcElement, tid = $.getUid( target )
                            //如果发现孩子是表单元素并且没有注册propertychange事件,则为其注册一个,那么它们在变化时就会发过来通知顶层元素
                            if ( rform.test( target.tagName) && !subscriber[ tid ] ) {
                                subscriber[ tid] = target;//表明其已注册
                                var publisher = $._data( target,"publisher") || $._data( target,"publisher",{} );
                                publisher[ $.getUid(src) ] = src;//此孩子可能同时要向N个顶层元素报告变化
                                $.fn.on.call( target,"propertychange._change", changeNotify );
                                //允许change事件可以通过fireEvent("onchange")触发
                                if(type === "change"){
                                    $._data(src, "_change_fire", $.bind(target, "change", changeFire.bind(target, e) ));
                                }
                            }
                        }));
                        if( fix ){//如果是事件绑定
                            src.fireEvent("onbeforeactivate")
                        }
                    }),
                    teardown: delegate(function( src, els, i ){
                        $.unbind( src, "beforeactive", $._data( src, "_beforeactivate") );
                        $.unbind( src, "change", $._data(src, "_change_fire")  );
                        els = $.removeData( src, "subscriber", true ) || {};
                        for( i in els){
                            facade.unbind.call( els[i], "._change" );
                            var publisher = $._data( els[i], "publisher");
                            if(publisher){
                                delete publisher[ src.uniqueNumber ];
                            }
                        }
                    })
                }
            }
        }
        var adapter = facade.eventAdapter;
        //submit事件的冒泡情况----IE6-9 :form ;FF: document; chrome: window;safari:window;opera:window
        //reset事件的冒泡情况----FF与opera能冒泡到document,其他浏览器只能到form
        "submit,reset".replace( $.rword, function( type ){
            adapter[ type ] = {
                setup: delegate(function( src ){
                    $.fn.on.call( src, "click._"+type+" keypress._"+type, function( e ) {
                        var el = e.target;
                        if( el.form && (adapter[ type ].keyCode[ e.which] || adapter[ type ].kind[  el.type ] ) ){
                            facade._dispatch( [ src ], type, e );
                        }
                    });
                }),
                keyCode: $.oneObject(type == "submit" ? "13,108" : "27"),
                kind:  $.oneObject(type == "submit" ? "submit,image" : "reset"),
                teardown: delegate(function( src ){
                    facade.unbind.call( src, "._"+type );
                })
            };
        });
    });
    //2012.5.1 fix delegate BUG将submit与reset这两个适配器合而为一
    
  • 相关阅读:
    STL源码剖析之_allocate函数
    PAT 1018. Public Bike Management
    PAT 1016. Phone Bills
    PAT 1012. The Best Rank
    PAT 1014. Waiting in Line
    PAT 1026. Table Tennis
    PAT 1017. Queueing at Bank
    STL源码剖析之list的sort函数实现
    吃到鸡蛋好吃,看看是哪只母鸡下的蛋:好用的Sqlite3
    cJSON
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2516987.html
Copyright © 2011-2022 走看看