/**
* @module event
* @author lifesinger@gmail.com
*/
KISSY.add('event', function(S, undef) {
var doc = document,
DOM = S.DOM,
simpleAdd = doc.addEventListener ?
function(el, type, fn, capture) {
if (el.addEventListener) {
el.addEventListener(type, fn, !!capture);
}
} :
function(el, type, fn) {
if (el.attachEvent) {
el.attachEvent('on' + type, fn);
}
},
simpleRemove = doc.removeEventListener ?
function(el, type, fn, capture) {
if (el.removeEventListener) {
el.removeEventListener(type, fn, !!capture);
}
} :
function(el, type, fn) {
if (el.detachEvent) {
el.detachEvent('on' + type, fn);
}
}, //红色部分的是原生的事件加载
EVENT_GUID = 'ksEventTargetId',//标识符
SPACE = ' ',
guid = S.now(),//时间戳
// { id: { target: el, events: { type: { handle: obj, listeners: [...] } } }, ... }
cache = { };//缓存
var Event = {//定义一个Event对象
EVENT_GUID: EVENT_GUID,
// such as: { 'mouseenter' : { fix: 'mouseover', handle: fn } }
special: { },
/**
* Adds an event listener.
* @param target {Element} An element or custom EventTarget to assign the listener to.
* @param type {String} The type of event to append.
* @param fn {Function} The event handler.
* @param scope {Object} (optional) The scope (this reference) in which the handler function is executed.
*/
add: function(target, type, fn, scope /* optional */) {//添加一个事件
if (batch('add', target, type, fn, scope)) return;//如果需要batch做一下批量,通过batch的逻辑
// Event.add([dom,dom])
//getID
var id = getID(target), isNativeEventTarget,
special, events, eventHandle, fixedType, capture;
// 不是有效的 target 或 参数不对
if (id === -1 || !type || !S.isFunction(fn)) return;
// 还没有添加过任何事件
if (!id) {//如果目前的对象没有添加过id
setID(target, (id = guid++));//set一个Id,并在cache里面存一个对应的对象,保存这个target和它对应的事件。
cache[id] = {
target: target,
events: { }
};
}
// 没有添加过该类型事件
events = cache[id].events;//events用来保存这个cache的events,用events来存储一个对象对应的event对象们
if (!events[type]) {
isNativeEventTarget = !target.isCustomEventTarget;
special = ((isNativeEventTarget || target._supportSpecialEvent)
&& Event.special[type]) || { };
eventHandle = function(event, eventData) {//eventHandle函数的定义,eventHandle是对事件添加的一层封装,原生的事件函数,只会有event这一个参数
if (!event || !event.fixed) {
event = new S.EventObject(target, event, type);//新new一个EventObject
}
if (S.isPlainObject(eventData)) {//把eventData mix到event对象上面,这里都没有区分是不是元素的事件。
//protect type
var typeo = event.type;
S.mix(event, eventData);
event.type = typeo;
}
if (special['setup']) {//如果是原生的事件或者是特殊的自定义事件,并定义了special方法,就通过special的setup方法来执行这个
special['setup'](event);
}
return (special.handle || Event._handle)(target, event);//返回值看special里面是否定义了handle,如果没有,就调用Event的_handle来处理target和event,默认的自定义事件的fire会来调用Event._handle方法,
};
events[type] = {//在events对象下面的类型下面建立对应的type的对象
handle: eventHandle,//每一个类型的事件的eventHandle都会保存在此一份,只不过原生的js会再用simpleAdd再做一层原生的调用
listeners: []
};
fixedType = special.fix || type;//fix capture
capture = special['capture'];
if (special['init']) {
special['init'].apply(null, S.makeArray(arguments));
}
if (isNativeEventTarget && special.fix !== false) {//如果是原生的事件并且fix不是false,那么就用原生的添加事件。
simpleAdd(target, fixedType, eventHandle, capture);
}
}
// 增加 listener
events[type].listeners.push({fn: fn, scope: scope || target});//对events对应的类型的listener下面push进对应的fn和eventHandle。
},
__getListeners:function(target, type) {//获取一个event对象的Listeners
var events = Event.__getEvents(target) || {},
eventsType,
listeners = [];
if ((eventsType = events[type])) {
listeners = eventsType.listeners;
}
return listeners;
},
__getEvents:function(target) {//获取一个对象上面的事件
var id = getID(target),c,
events;
if (id === -1) return; // 不是有效的 target
if (!id || !(c = cache[id])) return; // 无 cache
if (c.target !== target) return; // target 不匹配
events = c.events || { };
return events;
},
/**
* Detach an event or set of events from an element.
*/
remove: function(target, type /* optional */, fn /* optional */, scope /* optional */) {
if (batch('remove', target, type, fn, scope)) return;
var events = Event.__getEvents(target),
id = getID(target),
eventsType,
listeners,
len,
i,
j,
t,
isNativeEventTarget = !target.isCustomEventTarget,//isCustomEventTarget是外部传入的一个配置属性
special = ((isNativeEventTarget || target._supportSpecialEvent)
&& Event.special[type]) || { };
if (events === undefined) return;
scope = scope || target;
if ((eventsType = events[type])) {
listeners = eventsType.listeners;
len = listeners.length;
// 移除 fn
if (S.isFunction(fn) && len) {
for (i = 0,j = 0,t = []; i < len; ++i) {
if (fn !== listeners[i].fn
|| scope !== listeners[i].scope) {
t[j++] = listeners[i];
}
}
eventsType.listeners = t;
len = t.length;
}
// remove(el, type) or fn 已移除光
if (fn === undef || len === 0) {
if (!target.isCustomEventTarget) {
special = Event.special[type] || { };
if (special.fix !== false)
simpleRemove(target, special.fix || type, eventsType.handle);
}
delete events[type];
}
}
if (special.destroy) {
special.destroy.apply(null, S.makeArray(arguments));
}
// remove(el) or type 已移除光
if (type === undef || S.isEmptyObject(events)) {
for (type in events) {
Event.remove(target, type);
}
delete cache[id];
removeID(target);
}
},
_handle: function(target, event) {
/* As some listeners may remove themselves from the
event, the original array length is dynamic. So,
let's make a copy of all listeners, so we are
sure we'll call all of them.*/
var listeners = Event.__getListeners(target, event.type);
listeners = listeners.slice(0);
var ret,
gRet,
i = 0,
len = listeners.length,
listener;
for (; i < len; ++i) {
listener = listeners[i];
ret = listener.fn.call(listener.scope, event);
//有一个 false,最终结果就是 false
if (gRet !== false) {
gRet = ret;
}
// 和 jQuery 逻辑保持一致
// return false 等价 preventDefault + stopProgation
if (ret !== undefined) {
event.result = ret;
if (ret === false) {
event.halt();
}
}
if (event.isImmediatePropagationStopped) {
break;
}
}
return gRet;
},
_getCache: function(id) {
return cache[id];
},
__getID:getID,
_simpleAdd: simpleAdd,
_simpleRemove: simpleRemove
};
// shorthand
Event.on = Event.add;
function batch(methodName, targets, types, fn, scope) {//batch方法,在add或者是remove之前做一层批量的处理
// on('#id tag.className', type, fn)
if (S.isString(targets)) {
targets = S.query(targets);//获取targets对象
}
// on([targetA, targetB], type, fn)
if (S.isArray(targets)) {//如果有多个targets,那么就在Event对象下面对应的方法下面传入参数,不处理多对象多事件的情况
S.each(targets, function(target) {
Event[methodName](target, types, fn, scope);
});
return true;
}
// on(target, 'click focus', fn)
if ((types = S.trim(types)) && types.indexOf(SPACE) > 0) {//一个对象有多个事件使用同一个事件函数
S.each(types.split(SPACE), function(type) {
Event[methodName](targets, type, fn, scope);
});
return true;
}
}
function getID(target) {//getID 如果是一个dom节点或一个对象,就取这个节点的EVENT_GUID属性,否则返回-1
return isValidTarget(target) ? DOM.data(target, EVENT_GUID) : -1;
}
function setID(target, id) {//setID,如果是一个dom节点或一个对象,就给这个节点加上一个EVENT_GUID属性
if (isValidTarget(target)) {
DOM.data(target, EVENT_GUID, id);
}
}
function removeID(target) {//removeID,删除一个dom节点或一个对象的EVENT_GUID属性
DOM.removeData(target, EVENT_GUID);
}
function isValidTarget(target) {//isValidTarget方法
// 3 - is text node
// 8 - is comment node
return target && target.nodeType !== 3 && target.nodeType !== 8;
}
S.Event = Event;
});
分享到:
相关推荐
KISSY.Suggest 仿百度、淘宝输入提示补全功能的组件及实例!值得下载看看!资源免费,大家分享!! 更多免费资源 http://ynsky.download.csdn.net/
Web常用UI库 kissy ,kissy 是淘宝一个开源的 JavaScript 库,包含的组件有:日历、图片放大镜、卡片切换、...
NULL 博文链接:https://nopainnogain.iteye.com/blog/838608
kissy.js 提供小程序开发中一些常用的工具函数,有完整的接口文档。 下载地址:http://7te9kq.com1.z0.glb.clouddn.com/wxapp/kissydocs.html 本站下载:kissy.js (此图片来源于网络,如有侵权,请联系删除! ) 示例...
kissy-1.4.8.zip,淘宝最新前端开发包
本文所述的kissy是仅指其内核部分的kissy.js中的语言与框架设计思想。KISSY项目的开源网站是:http://kissyteam.github.com/ kissy怎么使用呢? 尽管在KissyUI向kissy内核化的过程中,我们提出了一些新的概念与框架...
高发展前途的web前端开发利器--kissy,中文文档。拥有该文档后不必再上网到处找,一切尽在其中。
Kissy 15天学会.zip欢迎下载!!!
use时, KISSY.use('gallery/pagination/1.0/pagination,gallery/pagination/1.0/tmp/friends,gallery/pagination/1.0/tmp/demo.css,gallery/pagination/1.0/assets/pagination.css', function(S, P, FriendList, ...
bee-demobee-demo是由。调试模块文件使用CMD规范,是无法使用源码直接调试的,所以bee 内置了个本地静态...}KISSY.config({ packages: [ { name: 'bee-demo', base: base, ignorePackageNameInUri: true, debug: tru
这是一个基于KISSY的新人引导组件,当用户第一次访问,或用户多次访问但未销毁引导功能的时候页面会出现一个引导浮层。用户可以点击“上一个”、“下一个”、“跳过”、“完成”,四个按钮操作复层,点击右上角的...
Kissy学习教程.rarKissy学习教程.rarKissy学习教程.rarKissy学习教程.rar
淘宝发布开源编辑器:KISSY Editor,和我们在 WordPress 后台使用的富文本编辑器 TinyMCE 一样,它可以让我们在线编辑和格式化文本,但是相比 TinyMCE KISSY Editor 更加轻巧,更加适合国内的网络环境。 KISSY ...
书写特效 kissyteam-kissyteam.github.com-901d2cd.rar
KISSY提供稳定的核心,包括 oo、dom、Event、Anim、Ajax 等;强大且易用的脚本加载器,特有的 loader;丰富的UI组件,包括 Switchable、Overlay、Draggable and Droppable 等。KISSY具备模块化、高扩展性、组件齐全...
js KISSY框架阿里云滑动下拉导航菜单效果代码 js KISSY框架阿里云滑动下拉导航菜单效果代码 js KISSY框架阿里云滑动下拉导航菜单效果代码 js KISSY框架阿里云滑动下拉导航菜单效果代码
KISSY 1.4.8,一个淘宝用的类似jQuery的前端框架
kissy模块化实践.taobao 前端架构Kissy介绍
KISSY Editor 是开源项目 KISSY UI Library 的一个组件。KISSY 目前基于 YUI 2.x 开发,目标是打造一系列小巧灵活、简洁实用、使用起来让人感觉愉悦的 UI 组件。目前已有 CSS 基础框架、搜索提示 Suggest 和今天发布...