`

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

阅读更多

       在ExtJs源码分析与学习—ExtJs事件机制(一)中分析了ExtJs对原生浏览器事件的封装。这篇进一步分析ExtJs对事件的封装和扩充。ExtJs会对浏览器本身的事件进行转换,是通过类Ext.EventObject来实现的,该类中通过自执行匿名函数返回Ext.EventObjectImpl对象,该对象用到了Ext.lib.Event(对原生浏览器事件的扩展)。

 

Ext.EventObject = function(){
    var E = Ext.lib.Event,
    …
    Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);
        }
    };

    Ext.EventObjectImpl.prototype = {
       …
};

    return new Ext.EventObjectImpl();
}();

 

下面看Ext.EventObject中代码的实现

 

// safari keypress events for special keys return bad keycodes
safariKeys = {
            3 : 13, // enter
            63234 : 37, // left
            63235 : 39, // right
            63232 : 38, // up
            63233 : 40, // down
            63276 : 33, // page up
            63277 : 34, // page down
            63272 : 46, // delete
            63273 : 36, // home
            63275 : 35  // end
        },

 该对象是为了兼容旧版本safari浏览器对部分键的按键事件返回值的处理,与其他浏览器的统一。

 

// normalize button clicks
 btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};

 由于IE浏览器与其他浏览器的按键值(e.button)不同,所以定义该对象是为了实现所有浏览器的兼容。兼容后,0为左键,1为中键,2为右键。

接下来是类Ext.EventObjectImpl的定义

 

Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);
        }
};

 该类中对浏览器原生事件e进行了包装,调用了private method setEvent,setEvent是定义在Ext.EventObjectImpl.prototype下的

 

        /** @private */
        setEvent : function(e){
            var me = this;
            if(e == me || (e && e.browserEvent)){ // already wrapped
                return e;
            }
            me.browserEvent = e;//把浏览器的原始事件保存到browserEvent中,可以作为是否包装的标识
            if(e){
                // normalize buttons
            	//该段代码处理了不同按键返回的e.button
                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);//e.which原本是键盘事件
                if(clickRe.test(e.type) && me.button == -1){
                    me.button = 0;
                }
                me.type = e.type;//事件名
                //三个功能组合键
                me.shiftKey = e.shiftKey;
                // mac metaKey behaves like ctrlKey
                me.ctrlKey = e.ctrlKey || e.metaKey || false;
                me.altKey = e.altKey;
                
                //键盘事件的keywode,and charcode 
                // in getKey these will be normalized for the mac
                me.keyCode = e.keyCode;
                me.charCode = e.charCode;
                
                // cache the target for the delayed and or buffered events
                //事件目标,E.getTarget(e)处理了不同浏览器的返回结果
                me.target = E.getTarget(e);
                // same for XY
                me.xy = E.getXY(e);//Ext自定义的坐标属性
            }else{//如果没有传入事件,则恢复属性为原始值
                me.button = -1;
                me.shiftKey = false;
                me.ctrlKey = false;
                me.altKey = false;
                me.keyCode = 0;
                me.charCode = 0;
                me.target = null;
                me.xy = [0, 0];
            }
            return me;
        },

 该方法首先判断事件是否包装过,如已经包装了,则直接返回该包装的事件。
 me.browserEvent = e;//把浏览器的原始事件保存到browserEvent中
 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);//e.which原本是键盘事件
     if(clickRe.test(e.type) && me.button == -1){
         me.button = 0;
 }
该段代码处理了不同按键返回不同的e.button
其他代码的功能,可参见代码注释

 

 

接着看stopEvent方法

 

stopEvent : function(){
            var me = this;
            if(me.browserEvent){
                if(me.browserEvent.type == 'mousedown'){
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
                }
                E.stopEvent(me.browserEvent);
            }
        },

 

停止事件(preventDefault和stopPropagation)。用来停止事件冒泡,阻止元素默认行为。需要说明的是对mousedown事件做了特殊处理Ext.EventManager.stoppedMouseDownEvent 实际是Ext.util.Event类的一个实例对象。如pub.stoppedMouseDownEvent = new Ext.util.Event();后续讲到Ext.EventManager时,会讲fire方法。

 

 /**
         * Prevents the browsers default handling of the event.
         */
        preventDefault : function(){
            if(this.browserEvent){
                E.preventDefault(this.browserEvent);
            }
        },

        /**
         * Cancels bubbling of the event.
         */
        stopPropagation : function(){
            var me = this;
            if(me.browserEvent){
                if(me.browserEvent.type == 'mousedown'){
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
                }
                E.stopPropagation(me.browserEvent);
            }
        },

 对preventDefault(阻止浏览器默认行为处理事件)和stopPropagation(取消事件冒泡)在该类中的实现,实际上还是调用Ext.lib.Event中的原生方法

 

接着看其他代码

 

 /**
         * 返回该事件键盘字符代码
         * Gets the character code for the event.
         * @return {Number} 键盘代码
         */
        getCharCode : function(){
            return this.charCode || this.keyCode;
        },

        /**
         * 返回一个常规化的事件键盘代码,对Safari进行了特殊处理
         * Returns a normalized keyCode for the event.
         * @return {Number} The key code
         */
        getKey : function(){
            var k = this.keyCode || this.charCode;
            return Ext.isSafari ? (safariKeys[k] || k) : k;
        },

        /**
         * 获取事件X坐标。
         * Gets the x coordinate of the event.
         * @return {Number}
         */
        getPageX : function(){
            return this.xy[0];
        },

        /**
         * 获取事件Y坐标。
         * Gets the y coordinate of the event.
         * @return {Number}
         */
        getPageY : function(){
            return this.xy[1];
        },

        /**
         * 获取事件的时间。
         * Gets the time of the event.
         * @return {Number}
         */
        getTime : function(){
            if(this.browserEvent){
                return E.getTime(this.browserEvent);
            }
            return null;
        },
        
        /**
         * 获取事件的页面坐标。
         * Gets the page coordinates of the event.
         * @return {Array} xy值,格式[x, y]。The xy values like [x, y]
         */
        getXY : function(){
            return this.xy;
        },

       /**
         * 获取事件的目标对象。
         * Gets the target for the event.
         * @param {String} selector (可选的) 一个简易的选择符,用于筛选目标或查找目标的父级元素。(optional) A simple selector to filter the target or look for an ancestor of the target
         * @param {Number/Mixed} maxDepth (可选的)搜索的最大深度(数字或是元素,默认为10||document.body)。(optional) The max depth to search as a number or element (defaults to 10 || document.body)
         * @param {Boolean} returnEl (可选的) True表示为返回Ext.Element的对象而非DOM节点。(optional) True to return a Ext.Element object instead of DOM node
         * @return {HTMLelement}
         */
        getTarget : function(selector, maxDepth, returnEl){
            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
        },


        /**
         * 获取相关的目标对象。
         * Gets the related target.
         * @return {HTMLElement}
         */
        getRelatedTarget : function(){
            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
        },

        /**
         * 常规化鼠标滚轮的有限增量(速度)。
         * IE/Safari/Chrome/Opera中使用事件对象的wheelDelta属性,Firefox则使用detail属性。
		   属性的方向值也不一样,IE向前滚 > 0为120,相反在-120,Firefox向后滚 > 0为3,相反则-3。
         * Normalizes mouse wheel delta across browsers
         * @return {Number} The delta
         */
        getWheelDelta : function(){
            var e = this.browserEvent;
            var delta = 0;
            if(e.wheelDelta){ /* IE/Opera. */
                delta = e.wheelDelta/120;
            }else if(e.detail){ /* Mozilla case. */
                delta = -e.detail/3;
            }
            return delta;
        },

getTarget 方法用到了Ext.fly,一个关键的方法,利用共享模式实现的,后续待讲

 

下面看方法within

 

      within : function(el, related, allowEl){
            if(el){
                var t = this[related ? "getRelatedTarget" : "getTarget"]();
                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
            }
            return false;
        }

如果该事件的目标对象是el的子元素,则返回true;如果allowEl设为true时,该事件的目标对象等于el也返回true。关于这个方法的理解,请看例子:

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<title>Ext.EventObject.within method demo</title>
		<meta http-equiv="content-type" content="text/html; charset=UTF-8">
		<link rel="stylesheet" type="text/css"
			href="../ext-3.3.1/resources/css/ext-all.css" />
		<style type="text/css">
			div {
				border: 1px solid blue;
				padding: 40px;
				margin: 10px;
			}
		</style>
		
		<script type="text/javascript"
			src="../ext-3.3.1/adapter/ext/ext-base-debug.js"></script>
		<script type="text/javascript"
			src="../ext-3.3.1/ext-all-debug-w-comments.js"></script>
		<script type="text/javascript"
			src="../ext-3.3.1/src/locale/ext-lang-zh_CN.js"></script>
		<script type="text/javascript" src="../ext-3.3.1/src/debug.js"></script>
		<!-- 调试脚本 -->
		<script type="text/javascript">
			Ext.onReady(function() {
			  Ext.BLANK_IMAGE_URL = '../ext-3.3.1/resources/images/default/s.gif';
			  Ext.QuickTips.init();
			        Ext.getBody().on('click', function(e){
			            if(e.within('some-el')){//如果该事件的目标对象是some-el的子元素,则返回true
			                alert('是在some-el的孩子节点上点击的!');
			            }else{
			            	alert('你的点击不是some-el的孩子节点');
			            }
			        });
			
			        Ext.getBody().on('click', function(e,t){
			            if((t.id == 'some-el') && !e.within(t, true)){//如果allowEl设为true时,该事件的目标对象等于el也返回true
			                alert('直接在some-el上点击了鼠标!');
		                }
		            });
	 		 });
		
		</script>
	</head>

	<body>
		<div id="some-el">
			<div id="some-el2">
				Ext.EventObject.within demo
			</div>
		</div>
		<br/>
		<div id="some-el3">
			<div id="some-el4">
				不是some-el节点
			</div>
		</div>
	</body>
</html>
 

以上介绍了Ext事件 Ext.EventObject 对浏览器原生事件的包装和扩展,实现了个浏览器之间的兼容。

分享到:
评论

相关推荐

    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(第二版)随书源码

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

    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插件。此外,熟悉EXTJS的源码也有助于解决在...

    ExtJs源码以及文档相关资料

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

    ExtJs框架系列之filetree 源码

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

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

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

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

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

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

    "深入浅出ExtJS随书源码--EXTJS2.0"是针对ExtJS 2.0版本的学习资源,通常与一本相关书籍配套,帮助读者通过实际代码加深对ExtJS的理解。 源码分析: 1. **组件系统**: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