`

ExtJs源码分析与学习—ExtJs事件机制(五)

阅读更多

      最近一直忙着做产品,所以好久没有写文章了,下面接着把ExtJs事件机制最后一点内容写完。主要是介绍Ext提供的三个辅助实现事件类——快捷键、导航键和鼠标按键事件。

 

快捷键 Ext.KeyMap

    该功能的实现被封装在类Ext.KeyMap中

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方法的实现

 

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方法,把事件注册到元素上

 

enable: function(){
		if(!this.enabled){
		    this.el.on(this.eventName, this.handleKeyDown, this);
		    this.enabled = true;
		}
	},

为指定的el元素注册事件

例子:常用复制、剪切、粘贴的实现

 

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中,首先看其构造函数

 

 

Ext.KeyNav = function(el, config){
    this.el = Ext.get(el);
    Ext.apply(this, config);
    if(!this.disabled){//如果被禁用则激活
        this.disabled = true;
        this.enable();//注册监听函数
    }
};

    再看注册监听函数

 

   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起了代理作用

 

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"
},

例子

 

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,首先看构造函数

 

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

 

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

 

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函数

 

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源码分析与开发实例宝典-开发的效果图.rar

    在《EXTJS源码分析与开发实例宝典》这本书中,读者可以深入理解EXTJS的内部机制,学习如何利用EXTJS进行高效开发。 标题"EXTJS源码分析与开发实例宝典-开发的效果图.rar"暗示了书中的内容可能包含了EXTJS的源码解析...

    Extjs源码分析与开发实例宝典

    《Extjs源码分析与开发实例宝典》全面介绍了ExtJS的技术细节和开发实践,是学习和掌握ExtJS不可或缺的资源。通过对本书的深入阅读,开发者不仅可以理解ExtJS的工作原理,还能学会如何运用ExtJS构建高效、美观的Web...

    资料:包括extjs2.0源码

    6. **图表组件**:EXTJS 2.0内置了各种图表类型,如柱状图、饼图、线图等,适用于数据可视化需求,源码分析有助于定制高级图表功能。 7. **Ajax交互**:EXTJS 2.0通过Ajax技术实现与服务器的异步通信,提供了强大的...

    Django整合Extjs源码

    **Django整合ExtJS源码解析** 在Web开发领域,Django作为一个强大的Python Web框架,以其高效、安全和可扩展性而备受青睐。与此同时,ExtJS是一个JavaScript库,用于构建富客户端应用程序,提供了丰富的组件和数据...

    ExtJS 3.4 源码包

    - **调试工具**:利用浏览器的开发者工具,可以追踪ExtJS源码中的错误和性能瓶颈。 - **主题定制**:ExtJS允许自定义皮肤,通过修改CSS文件,可以调整应用的视觉样式。 6. **与其他技术集成** - **PHP, ASP.NET,...

    ExtJs 实例+ExtJs中文教程(学习extjs必备)

    最后,结合源码分析,提升你的编程水平,能够更好地应对复杂的应用需求。 总之,ExtJs是一个强大的JavaScript框架,通过学习提供的实例和中文教程,结合具体的代码实践,你将能够开发出功能丰富、用户体验优秀的Web...

    ExtJS源码分析与开发实例宝典--书中代码

    核心技术部分深入讲解Ext JS的核心基础知识,包括JS原生对象的扩展、事件机制、 模板模型、数据模型,包括一个机制、两个模型及六个扩展。基于元素的开发部分讲解了在DOM元素基 础上扩展的Ext JS元素,包括元素操作...

    Extjs 4.0 源码说明文档入门手册 和示例

    源码分析: 在`ext-4.0.0`目录中,你将找到ExtJS 4.0的核心源代码。这些文件主要分为以下几个部分: 1. `src`目录:这是ExtJS的核心源码存放处,包含了所有组件、类和工具函数。每个主要的组件或功能都有自己的子...

    掏钱学ExtJs完全版附全部源码- 康海涛

    康海涛的"掏钱学ExtJs完全版"可能是一份全面的学习资料,涵盖了ExtJs的基础到高级应用,包括源码分析,旨在帮助学习者深入理解和掌握这一技术。 首先,ExtJs的核心是其组件模型。它提供了大量的预定义组件,如表格...

    extJS3.1源码及demo

    通过下载并研究"ext-3.1.0"这个压缩包中的源码和示例,开发者不仅可以学习到ExtJS的基本用法,还能深入理解其内部机制,这对于提升JavaScript开发技能和扩展自定义功能非常有帮助。不过需要注意,随着技术的发展,...

    ExtJs源码以及文档相关资料

    这个资料包“ExtJs源码以及文档相关资料”显然包含了ExtJS 4.1.1版本的源代码和相关的文档,这对于深入理解ExtJS的工作原理和学习如何使用它是极为宝贵的资源。 首先,ExtJS 4.1.1是该框架的一个稳定版本,发布于...

    EXTJS部分中文源码

    EXTJS的源码学习可以帮助开发者深入理解其内部机制,如数据管理、事件系统、布局管理等。通过分析源码,开发者可以学习到如何自定义组件,优化性能,甚至开发自己的EXTJS插件。此外,熟悉EXTJS的源码也有助于解决在...

    ExtJs框架系列之filetree 源码

    - **事件监听**:FileTree中的各种交互行为(如点击、拖放、展开/折叠)都可通过事件监听机制来响应和处理。 深入研究这些源码,可以帮助开发者更好地掌握ExtJs框架的使用,尤其是对文件系统操作的需求。同时,通过...

    深入剖析ExtJS_2.2实现及应用

    《深入剖析ExtJS_2.2实现及应用》是一本专为高级Web开发者设计的书籍,专注于探讨...它提供的源码分析和实例应用相结合的学习路径,使得读者能在实践中深化理论,在理论中增强实践,从而达到"厚积薄发"的学习效果。

    合同管理系统 extjs开发的 让大家一起学习

    5. **提醒与通知**:EXTJS支持事件监听和触发,可以实现合同到期、审批超时等重要事件的自动提醒。 在实际部署过程中,`setup.exe`是安装程序,用户可以通过运行这个文件来安装合同管理系统。`安装说明.txt`则提供...

    深入浅出ExtJS随书源码--EXTJS2.0

    "深入浅出ExtJS随书源码--EXTJS2.0"是针对ExtJS 2.0版本的学习资源,通常与一本相关书籍配套,帮助读者通过实际代码加深对ExtJS的理解。 源码分析: 1. **组件系统**:ExtJS的核心是其组件模型,其中包括各种可...

    深入浅出extjs(第二版)随书源码

    该随书源码包含三个不同版本的ExtJS源码:ext-3.0.0、ext-3.1.1和ext-3.2.0。这涵盖了ExtJS 3.x的主要迭代,每个版本都可能包含新的特性和改进。通过学习这些源码,读者可以了解到ExtJS的历史演变,以及在不同版本间...

    ExtJs+java(SSH)项目源码

    **项目实战源码分析** 这个项目源码中,你将看到以下几个部分: 1. **前端部分**:主要使用ExtJs编写,包括各种页面布局、组件、交互逻辑。你可以在`js`目录下找到相关的JavaScript文件,这些文件定义了ExtJs组件和...

    ExtJS5学习之Grid与Grid之间的数据拖拽

    在"ExtJS5学习之Grid与Grid之间的数据拖拽"这个主题中,我们将深入探讨如何实现这种交互功能,以及背后的机制和重要知识点。 首先,我们要了解ExtJS的Grid组件。Grid是一种可配置的表格视图,它可以显示大量的结构...

    asp.net与extjs开发点卡在线销售系统完整源码

    《ASP.NET与EXTJS开发的点卡在线销售系统详解》 在互联网技术高速发展的今天,电子支付和在线交易已经成为日常生活的一部分。点卡作为一种便捷的预付费方式,广泛应用于游戏、软件激活、网络服务等多个领域。本文将...

Global site tag (gtag.js) - Google Analytics