1 /** 2 * @fileOverview responsible for handling event from browser to KISSY Event 3 * @author yiminghe@gmail.com 4 */ 5 KISSY.add("event/handle", function (S, DOM, _data, special) { 6 7 function getEvents(target) { 8 // 获取事件描述 9 var eventDesc = _data._data(target); 10 return eventDesc && eventDesc.events; 11 } 12 13 function getHandlers(target, type) { 14 var events = getEvents(target) || {}; 15 return events[type] || []; 16 } 17 18 return function (currentTarget, event) { 19 /* 20 As some listeners may remove themselves from the 21 event, the original array length is dynamic. So, 22 let's make a copy of all listeners, so we are 23 sure we'll call all of them. 24 */ 25 /** 26 * DOM3 Events: EventListenerList objects in the DOM are live. ?? 27 */ 28 var handlers = getHandlers(currentTarget, event.type), 29 target = event.target, 30 currentTarget0, 31 allHandlers = [], 32 ret, 33 gRet, 34 handlerObj, 35 i, 36 j, 37 delegateCount = handlers.delegateCount || 0, 38 len, 39 currentTargetHandlers, 40 currentTargetHandler, 41 handler; 42 43 // collect delegated handlers and corresponding element 44 if (delegateCount && 45 // by jq 46 // Avoid disabled elements in IE (#6911) 47 // non-left-click bubbling in Firefox (#3861),firefox 8 fix it 48 !target.disabled) { 49 while (target != currentTarget) { 50 currentTargetHandlers = []; 51 for (i = 0; i < delegateCount; i++) { 52 handler = handlers[i]; 53 if (DOM.test(target, handler.selector)) { 54 currentTargetHandlers.push(handler); 55 } 56 } 57 if (currentTargetHandlers.length) { 58 allHandlers.push({ 59 currentTarget:target, 60 currentTargetHandlers:currentTargetHandlers 61 }); 62 } 63 target = target.parentNode || currentTarget; 64 } 65 } 66 67 // root node's handlers is placed at end position of add handlers 68 // in case child node stopPropagation of root node's handlers 69 allHandlers.push({ 70 currentTarget:currentTarget, 71 currentTargetHandlers:handlers.slice(delegateCount) 72 }); 73 74 // backup eventType 75 var eventType = event.type, 76 s, 77 t, 78 _ks_groups = event._ks_groups; 79 for (i = 0, len = allHandlers.length; 80 !event.isPropagationStopped && i < len; 81 ++i) { 82 83 handlerObj = allHandlers[i]; 84 currentTargetHandlers = handlerObj.currentTargetHandlers; 85 currentTarget0 = handlerObj.currentTarget; 86 event.currentTarget = currentTarget0; 87 for (j = 0; !event.isImmediatePropagationStopped && 88 j < currentTargetHandlers.length; 89 j++) { 90 91 currentTargetHandler = currentTargetHandlers[j]; 92 93 // handler's group does not match specified groups (at fire step) 94 if (_ks_groups && 95 (!currentTargetHandler.groups || 96 !(currentTargetHandler.groups.match(_ks_groups)))) { 97 continue; 98 } 99 100 var data = currentTargetHandler.data; 101 102 // restore originalType if involving delegate/onFix handlers 103 event.type = currentTargetHandler.originalType || eventType; 104 105 // scope undefined 时不能写死在 listener 中,否则不能保证 clone 时的 this 106 if ((s = special[event.type]) && s.handle) { 107 t = s.handle(event, currentTargetHandler, data); 108 // can handle 109 if (t.length > 0) { 110 ret = t[0]; 111 } 112 } else { 113 ret = currentTargetHandler.fn.call( 114 currentTargetHandler.scope || currentTarget, 115 event, data 116 ); 117 } 118 // 和 jQuery 逻辑保持一致 119 // 有一个 false,最终结果就是 false 120 // 否则等于最后一个返回值 121 if (gRet !== false) { 122 gRet = ret; 123 } 124 // return false 等价 preventDefault + stopProgation 125 if (ret === false) { 126 event.halt(); 127 } 128 } 129 } 130 131 // fire 时判断如果 preventDefault,则返回 false 否则返回 true 132 // 这里返回值意义不同 133 return gRet; 134 } 135 }, { 136 requires:['dom', './data', './special'] 137 });