ExtJs源码分析与学习—ExtJs事件机制(五)
2011-07-27 23:37
579 查看
最近一直忙着做产品,所以好久没有写文章了,下面接着把ExtJs事件机制最后一点内容写完。主要是介绍Ext提供的三个辅助实现事件类——快捷键、导航键和鼠标按键事件。
快捷键 Ext.KeyMap
该功能的实现被封装在类Ext.KeyMap中
Js代码
Ext.KeyMap = function(el, config, eventName){
this.el = Ext.get(el);
this.eventName = eventName || "keydown";
this.bindings = [];
if(config){
this.addBinding(config);
}
this.enable();
};
该类实现分为三步,首先找到注册快捷键的元素el,然后把config参数转换为事件的监听函数this.addBinding(config),最后再注册该监听函数this.enable()。先看addBinding方法的实现
Js代码
addBinding : function(config){
if(Ext.isArray(config)){
Ext.each(config, function(c){
this.addBinding(c);
}, this);
return;
}
var keyCode = config.key,
fn = config.fn || config.handler,
scope = config.scope;
if (config.stopEvent) {
this.stopEvent = config.stopEvent;
}
if(typeof keyCode == "string"){
var ks = [];
var keyString = keyCode.toUpperCase();
for(var j = 0, len = keyString.length; j < len; j++){
ks.push(keyString.charCodeAt(j));
}
keyCode = ks;
}
var keyArray = Ext.isArray(keyCode);
//代理按键的监听处理函数,对配置对象中的fn/handle函数进行代理加工处理
var handler = function(e){
//如果指定'shift', 'ctrl', 'alt',而事件对象没有按下指定的'shift', 'ctrl', 'alt',那么就不进行处理
if(this.checkModifiers(config, e)){
var k = e.getKey();
if(keyArray){
for(var i = 0, len = keyCode.length; i < len; i++){
if(keyCode[i] == k){
if(this.stopEvent){
e.stopEvent();
}
fn.call(scope || window, k, e);
return;
}
}
}else{
if(k == keyCode){
if(this.stopEvent){
e.stopEvent();
}
fn.call(scope || window, k, e);
}
}
}
};
this.bindings.push(handler);
},
config配置项支持以下属性
属性 类型 描述
---------- --------------- ----------------------------------------------------------------------
key String/Array 进行处理的单个keycode或keycodes组成的数组
shift Boolean True:只有shift按下的的同时处理key (默认false)
ctrl Boolean True:只有ctrl按下的的同时处理key (默认false)
handler Function 当KeyMap找到预期的组合键时所执行的函数
alt Boolean True:只有alt按下的的同时处理key (默认false)
fn Function 当组合键按下后回调函数
scope Object 回调函数的作用域
stopEvent Boolean 用来停止事件冒泡,阻止元素默认行为。
再看enable方法,把事件注册到元素上
Js代码
enable: function(){
if(!this.enabled){
this.el.on(this.eventName, this.handleKeyDown, this);
this.enabled = true;
}
},
为指定的el元素注册事件
例子:常用复制、剪切、粘贴的实现
Js代码
var config = [{//剪切
key : 'x',
ctrl : true,
fn : function() {
//cut
},
scope : this
},{//复制
key : 'c',
ctrl : true,
fn : function() {
//copy
},
scope : this
},{//粘贴
key : 'v',
ctrl : true,
fn : function() {
//paste
},
scope : this
},{//编辑
key : 'abcdefghigklmnopqrstuvwxyz0123456789',
ctrl : false,
shift : false,
alt : false,
fn : function(k, e) {
alert(k);
},
scope : this
}];
var map = new Ext.KeyMap("my-element", config);
导航键 Ext.KeyNav
导航键的实现被封装在类Ext.KeyNav中,首先看其构造函数
Js代码
Ext.KeyNav = function(el, config){
this.el = Ext.get(el);
Ext.apply(this, config);
if(!this.disabled){//如果被禁用则激活
this.disabled = true;
this.enable();//注册监听函数
}
};
再看注册监听函数
Js代码
enable: function() {
if (this.disabled) {
if (Ext.isSafari2) {
// call stopKeyUp() on "keyup" event
this.el.on('keyup', this.stopKeyUp, this);
}
this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
this.disabled = false;
}
},
IE及其他一些浏览器的keyPress事件不会对非字母数字键进行冒泡,所以采用keyDown事件替代keyPress事件。而该事件的处理函数relay起了代理作用
Js代码
relay : function(e){
var k = e.getKey(),
h = this.keyToHandler[k];
if(h && this[h]){
if(this.doRelay(e, this[h], h) !== true){
e[this.defaultEventAction]();
}
}
},
KeyToHandler是键名和键值对应的hash表,通过event对象获得了键值之后,再和Ext.KeyNav类中12个导航键名比较,看看其是否为导航键,如果是,再看看有没有注册的处理函数,有才运行该监听函数。
该导航键共提供了12个,分别为
keyToHandler : {
37 : "left",
39 : "right",
38 : "up",
40 : "down",
33 : "pageUp",
34 : "pageDown",
46 : "del",
36 : "home",
35 : "end",
13 : "enter",
27 : "esc",
9 : "tab"
},
例子
Js代码
var nav = new Ext.KeyNav("my-element", {
"left" : function(e){
this.moveLeft(e.ctrlKey);
},
"right" : function(e){
this.moveRight(e.ctrlKey);
},
"enter" : function(e){
this.save();
},
scope : this
});
鼠标按住事件 Ext.util.ClickRepeater
鼠标按住事件就是用鼠标按住某个元素,会根据指定的时间间隔来反复地执行同样的动作。该功能的实现被封装在类Ext.util.ClickRepeater,首先看构造函数
Js代码
constructor : function(el, config){
this.el = Ext.get(el);
this.el.unselectable();//元素内容不能选择
Ext.apply(this, config);
this.addEvents(
/**
* @event mousedown
* 当鼠标按下的时候触发。
* Fires when the mouse button is depressed.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"mousedown",
/**
* @event click
* 当元素被按下接受到按下的消息的时候出发,比mousedown事件慢。
* Fires on a specified interval during the time the element is pressed.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"click",
/**
* @event mouseup
* 当鼠标释放后触发。
* Fires when the mouse key is released.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"mouseup"
);
if(!this.disabled){
this.disabled = true;
this.enable();
}
// allow inline handler
if(this.handler){
this.on("click", this.handler, this.scope || this);
}
Ext.util.ClickRepeater.superclass.constructor.call(this);
},
该构造函数中调用了this.enable();来处理鼠标按下事件,然后如果配置项声明了handler处理函数,会把该函数注册到cilck事件中。下面看方法enable
Js代码
enable: function(){
if(this.disabled){
this.el.on('mousedown', this.handleMouseDown, this);
if (Ext.isIE){
this.el.on('dblclick', this.handleDblClick, this);
}
if(this.preventDefault || this.stopDefault){
this.el.on('click', this.eventOptions, this);
}
}
this.disabled = false;
},
该方法中给元素el注册了mousedown事件,如果是IE浏览器,还注册了dblclick事件,然后根据配置项来阻止默认或冒泡处理,下面看handleMouseDown
Js代码
handleMouseDown : function(e){
clearTimeout(this.timer);
this.el.blur();//除去焦点
if(this.pressClass){
this.el.addClass(this.pressClass);
}
this.mousedownTime = new Date();
Ext.getDoc().on("mouseup", this.handleMouseUp, this);
this.el.on("mouseout", this.handleMouseOut, this);
this.fireEvent("mousedown", this, e);
this.fireEvent("click", this, e);
// Do not honor delay or interval if acceleration wanted.
if (this.accelerate) {
this.delay = 400;
}
this.timer = this.click.defer(this.delay || this.interval, this, [e]);
},
当用户在某个元素上按下鼠标时,首先让该元素失去焦点,改变样式,同时还分别为鼠标按键松开或移出注册了监听函数,最后按指定的间隔来推迟运行click函数
Js代码
click : function(e){
this.fireEvent("click", this, e);
this.timer = this.click.defer(this.accelerate ?
this.easeOutExpo(this.mousedownTime.getElapsed(),
400,
-390,
12000) :
this.interval, this, [e]);
},
该函数递归调用click函数,如果设置了this.accelerate,时间间隔就会按一定的算法越运行越短,即运行click会越来越快。
快捷键 Ext.KeyMap
该功能的实现被封装在类Ext.KeyMap中
Js代码
Ext.KeyMap = function(el, config, eventName){
this.el = Ext.get(el);
this.eventName = eventName || "keydown";
this.bindings = [];
if(config){
this.addBinding(config);
}
this.enable();
};
该类实现分为三步,首先找到注册快捷键的元素el,然后把config参数转换为事件的监听函数this.addBinding(config),最后再注册该监听函数this.enable()。先看addBinding方法的实现
Js代码
addBinding : function(config){
if(Ext.isArray(config)){
Ext.each(config, function(c){
this.addBinding(c);
}, this);
return;
}
var keyCode = config.key,
fn = config.fn || config.handler,
scope = config.scope;
if (config.stopEvent) {
this.stopEvent = config.stopEvent;
}
if(typeof keyCode == "string"){
var ks = [];
var keyString = keyCode.toUpperCase();
for(var j = 0, len = keyString.length; j < len; j++){
ks.push(keyString.charCodeAt(j));
}
keyCode = ks;
}
var keyArray = Ext.isArray(keyCode);
//代理按键的监听处理函数,对配置对象中的fn/handle函数进行代理加工处理
var handler = function(e){
//如果指定'shift', 'ctrl', 'alt',而事件对象没有按下指定的'shift', 'ctrl', 'alt',那么就不进行处理
if(this.checkModifiers(config, e)){
var k = e.getKey();
if(keyArray){
for(var i = 0, len = keyCode.length; i < len; i++){
if(keyCode[i] == k){
if(this.stopEvent){
e.stopEvent();
}
fn.call(scope || window, k, e);
return;
}
}
}else{
if(k == keyCode){
if(this.stopEvent){
e.stopEvent();
}
fn.call(scope || window, k, e);
}
}
}
};
this.bindings.push(handler);
},
config配置项支持以下属性
属性 类型 描述
---------- --------------- ----------------------------------------------------------------------
key String/Array 进行处理的单个keycode或keycodes组成的数组
shift Boolean True:只有shift按下的的同时处理key (默认false)
ctrl Boolean True:只有ctrl按下的的同时处理key (默认false)
handler Function 当KeyMap找到预期的组合键时所执行的函数
alt Boolean True:只有alt按下的的同时处理key (默认false)
fn Function 当组合键按下后回调函数
scope Object 回调函数的作用域
stopEvent Boolean 用来停止事件冒泡,阻止元素默认行为。
再看enable方法,把事件注册到元素上
Js代码
enable: function(){
if(!this.enabled){
this.el.on(this.eventName, this.handleKeyDown, this);
this.enabled = true;
}
},
为指定的el元素注册事件
例子:常用复制、剪切、粘贴的实现
Js代码
var config = [{//剪切
key : 'x',
ctrl : true,
fn : function() {
//cut
},
scope : this
},{//复制
key : 'c',
ctrl : true,
fn : function() {
//copy
},
scope : this
},{//粘贴
key : 'v',
ctrl : true,
fn : function() {
//paste
},
scope : this
},{//编辑
key : 'abcdefghigklmnopqrstuvwxyz0123456789',
ctrl : false,
shift : false,
alt : false,
fn : function(k, e) {
alert(k);
},
scope : this
}];
var map = new Ext.KeyMap("my-element", config);
导航键 Ext.KeyNav
导航键的实现被封装在类Ext.KeyNav中,首先看其构造函数
Js代码
Ext.KeyNav = function(el, config){
this.el = Ext.get(el);
Ext.apply(this, config);
if(!this.disabled){//如果被禁用则激活
this.disabled = true;
this.enable();//注册监听函数
}
};
再看注册监听函数
Js代码
enable: function() {
if (this.disabled) {
if (Ext.isSafari2) {
// call stopKeyUp() on "keyup" event
this.el.on('keyup', this.stopKeyUp, this);
}
this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
this.disabled = false;
}
},
IE及其他一些浏览器的keyPress事件不会对非字母数字键进行冒泡,所以采用keyDown事件替代keyPress事件。而该事件的处理函数relay起了代理作用
Js代码
relay : function(e){
var k = e.getKey(),
h = this.keyToHandler[k];
if(h && this[h]){
if(this.doRelay(e, this[h], h) !== true){
e[this.defaultEventAction]();
}
}
},
KeyToHandler是键名和键值对应的hash表,通过event对象获得了键值之后,再和Ext.KeyNav类中12个导航键名比较,看看其是否为导航键,如果是,再看看有没有注册的处理函数,有才运行该监听函数。
该导航键共提供了12个,分别为
keyToHandler : {
37 : "left",
39 : "right",
38 : "up",
40 : "down",
33 : "pageUp",
34 : "pageDown",
46 : "del",
36 : "home",
35 : "end",
13 : "enter",
27 : "esc",
9 : "tab"
},
例子
Js代码
var nav = new Ext.KeyNav("my-element", {
"left" : function(e){
this.moveLeft(e.ctrlKey);
},
"right" : function(e){
this.moveRight(e.ctrlKey);
},
"enter" : function(e){
this.save();
},
scope : this
});
鼠标按住事件 Ext.util.ClickRepeater
鼠标按住事件就是用鼠标按住某个元素,会根据指定的时间间隔来反复地执行同样的动作。该功能的实现被封装在类Ext.util.ClickRepeater,首先看构造函数
Js代码
constructor : function(el, config){
this.el = Ext.get(el);
this.el.unselectable();//元素内容不能选择
Ext.apply(this, config);
this.addEvents(
/**
* @event mousedown
* 当鼠标按下的时候触发。
* Fires when the mouse button is depressed.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"mousedown",
/**
* @event click
* 当元素被按下接受到按下的消息的时候出发,比mousedown事件慢。
* Fires on a specified interval during the time the element is pressed.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"click",
/**
* @event mouseup
* 当鼠标释放后触发。
* Fires when the mouse key is released.
* @param {Ext.util.ClickRepeater} this
* @param {Ext.EventObject} e
*/
"mouseup"
);
if(!this.disabled){
this.disabled = true;
this.enable();
}
// allow inline handler
if(this.handler){
this.on("click", this.handler, this.scope || this);
}
Ext.util.ClickRepeater.superclass.constructor.call(this);
},
该构造函数中调用了this.enable();来处理鼠标按下事件,然后如果配置项声明了handler处理函数,会把该函数注册到cilck事件中。下面看方法enable
Js代码
enable: function(){
if(this.disabled){
this.el.on('mousedown', this.handleMouseDown, this);
if (Ext.isIE){
this.el.on('dblclick', this.handleDblClick, this);
}
if(this.preventDefault || this.stopDefault){
this.el.on('click', this.eventOptions, this);
}
}
this.disabled = false;
},
该方法中给元素el注册了mousedown事件,如果是IE浏览器,还注册了dblclick事件,然后根据配置项来阻止默认或冒泡处理,下面看handleMouseDown
Js代码
handleMouseDown : function(e){
clearTimeout(this.timer);
this.el.blur();//除去焦点
if(this.pressClass){
this.el.addClass(this.pressClass);
}
this.mousedownTime = new Date();
Ext.getDoc().on("mouseup", this.handleMouseUp, this);
this.el.on("mouseout", this.handleMouseOut, this);
this.fireEvent("mousedown", this, e);
this.fireEvent("click", this, e);
// Do not honor delay or interval if acceleration wanted.
if (this.accelerate) {
this.delay = 400;
}
this.timer = this.click.defer(this.delay || this.interval, this, [e]);
},
当用户在某个元素上按下鼠标时,首先让该元素失去焦点,改变样式,同时还分别为鼠标按键松开或移出注册了监听函数,最后按指定的间隔来推迟运行click函数
Js代码
click : function(e){
this.fireEvent("click", this, e);
this.timer = this.click.defer(this.accelerate ?
this.easeOutExpo(this.mousedownTime.getElapsed(),
400,
-390,
12000) :
this.interval, this, [e]);
},
该函数递归调用click函数,如果设置了this.accelerate,时间间隔就会按一定的算法越运行越短,即运行click会越来越快。
相关文章推荐
- ExtJs源码分析与学习—ExtJs事件机制(六)
- ExtJs源码分析与学习—ExtJs事件机制(一)
- ExtJs源码分析与学习—ExtJs事件机制(二)
- ExtJs源码分析与学习—ExtJs事件机制(三)
- ExtJs源码分析与学习—ExtJs事件机制(四)
- ExtJs源码分析与学习—ExtJs事件机制(四)
- Vue学习之源码分析--Vue.js事件机制(四)
- Android触摸屏事件派发机制详解与源码分析三(Activity篇)
- extjs学习--事件机制
- Android源码分析-点击事件派发机制
- rt-thread的IPC机制之事件源码分析
- Android源码分析-点击事件派发机制
- Android触摸事件派发机制源码分析之ViewGroup
- Android源码分析-点击事件派发机制
- Android触摸事件派发机制源码分析之Activity
- 深入理解Android事件分发机制之源码分析
- ExtJs源码分析与学习—ExtJs元素Element(三)
- ExtJs源码分析与学习—ExtJs核心代码扩展
- 源码分析android的事件分发机制
- Android源码分析-点击事件派发机制