1.总体架构
为两类事件提供接口,点击事件和拖拽事件,其中点击事件需要向元素添加preventClickEvent,以阻止默认的表单提交或文件上传事件发生。
两类事件都是通过向元素绑定mouseDown事件触发函数发生。
点击事件在_mouseDown函数中判断配置项中是否要求延时以及拖拽距离,如果没有,在_mouseDown函数中触发_mouseStart函数,并记录_mouseStarted(两次点击有效),第二次点击的时候调用_mouseUp函数,触发用户定义的_mouseStop函数,mouseStop函数里向元素添加preventClickEvent,该事件有过多疑问处;
拖拽事件在_mouseDown向文档节点绑定mousemove和mouseup事件,mouseMove事件中执行用户定义的_mouseStart函数,并记录_mouseStarted,方便第二次移动的时候直接判断该值,调用_mouseDrag函数,_mouseUp函数中执行_mouseStop函数。
2.插件的使用
配置项options
包括cancel(免于交互的element元素)、delay(规定的延时,在_mouseMove中判断该值,由结果决定_mouseDrag是否被触发)、distance(规定的移动距离,同样在_mouseMove中判断该值,由结果决定_mouseDrag是否被触发)
方法
_mouseDelayMet判断是否有延时;
_mouseDistanceMet判断移动距离是否符合要求;
_mouseInit绑定mousedown和click事件,click事件需要判断元素的preventClickEvent属性,由此决定是否执行;
_mouseDown将事件拆分成点击事件和拖拽事件两类,由配置项决定是否有函数被执行,点击事件触发_mouseUp和_mouseStart、_mouseStop函数,拖拽事件先向文档节点绑定mousemove、mouseup事件,再触发_mouseMove、_mouseUp和_mouseStart、_mouseDrag、_mouseStop函数;
_mouseMove拖拽事件触发_mouseStart、_mouseDrag函数;
_mouseUp触发_mouseStart函数;
接口
_mouseCapture返回否时意味着不触发交互事件;
_mouseDown鼠标按下时触发的函数;
_mouseDrag鼠标移动时触发的函数;
_mouseUp鼠标松开时触发的函数。
http://api.jqueryui.com/mouse/
3.JS及jQuery的新认识
在类中的function函数中,使用self或that代替this,用来指代类,避免this值可能的变更;
closest()从当前元素开始,沿着dom树向上寻找,包含当前元素;
parentsUntil()向上遍历寻找父级元素,传入的参数是遍历的截止位置;
contents()查询文本节点和html元素节点,可以获取iframe内的元素节点,部分功能同find();
event.pageX.left/top鼠标偏离文档编辑器的坐标;
event.which鼠标左键值为1,中键为2,右键为3,没有按鼠标为0;
event.button判断鼠标按键,ie9开始和标准浏览器相同,左键为0,中键为1,右键为2,ie8左键为1,中键为4,右键为2。
// 使用自调用匿名函数将构建的function函数作为factory的实参,define未定义时使用require模块化工具,否则将jquery传入function函数中 ( function( factory ) { if ( typeof define === "function" && define.amd ) { define( [ "jquery", "../ie", "../version", "../widget" ], factory ); } else { factory( jQuery ); } }( function( $ ) { // 各记录项mouseHandled、_mouseMoved、_mouseStarted在事件过程中记录为真,开始时为否则不执行该事件,事件结尾记录为否 // mouseHandled鼠标按下时判断,mousedown函数结尾处记录为真,阻止其他widget部件触发事件,鼠标松开时记录为否,代表执行完毕 // _mouseMoved鼠标按下时记录为否,鼠标移动时记录为真,处理间歇性的两次鼠标移动事件 /** * _mouseStarted当mouseStart返回值为真时记录为真,mouseUp事件开始的时候将其置为false,mousedrag执行前需要为真 * _mouseDown函数中mouseStart启动需要无延时、无移动距离,鼠标按下触发mouseStart函数,直接跳转至mouseUp函数,mouseUp函数中执行mouseStop函数,没有执行mouseMove函数 * _mouseMove函数中mouseStart启动时可以有延时,需要移动距离,鼠标移动时触发mouseMove函数,mouseMove函数中执行mouseStart、mouseDrag函数,最终跳转到mouseUp函数,并执行mouseStop函数 * _mouseMove函数随着鼠标每移动一个像素点反复执行, */ // mouseDelayMet为否时有延时,options.delay存在时延时触发,mouseDelayMet延时过程中赋值为真 var mouseHandled = false; $( document ).on( "mouseup", function() { mouseHandled = false; } ); return $.widget( "ui.mouse", { version: "@VERSION", options: { cancel: "input, textarea, button, select, option",// 免于交互的元素 distance: 1, delay: 0 }, // 绑定mouseDown事件,同时click不触发点击事件,this.started记录初始化是否完成 // click事件包含mousedown和mouseup事件 _mouseInit: function() { var that = this; this.element .on( "mousedown." + this.widgetName, function( event ) { return that._mouseDown( event ); } ) .on( "click." + this.widgetName, function( event ) { if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { $.removeData( event.target, that.widgetName + ".preventClickEvent" ); // 包含阻止事件冒泡stopPropgation的功能之外,也阻止该元素绑定的同类型事件 event.stopImmediatePropagation(); return false; } } ); this.started = false; }, /** * mouseDown函数中率先判断是否为无延时、无移动距离的事件,是则执行mouseStart函数,即鼠标按下时触发的函数 * 不是则在文档节点上绑定mousemove、mouseup事件,先后触发mouseStart、mouseMove函数,即鼠标移动时触发的函数 */ // mouseDestory函数用于在事件结尾处清空绑定在文档节点上的事件,问题是mouseUp函数中已经解除绑定??? _mouseDestroy: function() { this.element.off( "." + this.widgetName ); if ( this._mouseMoveDelegate ) { this.document .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); } }, _mouseDown: function( event ) { if ( mouseHandled ) { return; } this._mouseMoved = false; // _mouseStarted两次点击的时候有有效值?促发_mouseUp函数??? ( this._mouseStarted && this._mouseUp( event ) ); this._mouseDownEvent = event; var that = this, btnIsLeft = ( event.which === 1 ),// 鼠标左键 // event.target.nodeName works around a bug in IE 8 with disabled inputs (#7620) // closest()从当前元素开始,沿着dom树向上寻找,包含当前元素 // 不是鼠标左键点击,或者触发元素是表单元素及其子元素,或者_mouseCapture函数返回为否,则推出mouseDown函数,mouseCapture返回为否禁用交互事件 elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ? $( event.target ).closest( this.options.cancel ).length : false ); if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { return true; } // setTimeout回调函数的异步机制,后续代码块会先执行,即有延迟事件delay或规定距离distance的时候,后一条语句不被执行 // 在function中,用that代替this,避免this值可能发生的变化 this.mouseDelayMet = !this.options.delay; if ( !this.mouseDelayMet ) { this._mouseDelayTimer = setTimeout( function() { that.mouseDelayMet = true; }, this.options.delay ); } // 点击事件触发时event怎样传入回调函数中???event的C++接口原理??? // distance和delay均为0、mouseStart有返回值的情况,利用if语句执行mouseStart函数,阻止默认事件,如提交表单、按钮上传文件按钮 // 语句的作用是设置鼠标按下时的事件,_mouseStart即是_mousedown事件触发时执行的函数,取代默认的点击事件 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { this._mouseStarted = ( this._mouseStart( event ) !== false ); if ( !this._mouseStarted ) { event.preventDefault(); return true; } } /** * mouse.js将事件分为两类,一类是鼠标按下又松开,和点击事件起冲突,需要记录preventClickEvent阻止默认的点击事件,这一类事件触发的函数是mouseDown、mouseUp、mouseStart、mouseStop * 另一类是鼠标按下后移动了一段距离再松开,和点击事件没有冲突,不需要preventClickEvent阻止默认的点击事件,这一类事件触发的函数是mouseDown、mouseMove、mouseUp、mouseStart、mouseDrag、mouseStop */ if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { $.removeData( event.target, this.widgetName + ".preventClickEvent" ); } this._mouseMoveDelegate = function( event ) { return that._mouseMove( event ); }; this._mouseUpDelegate = function( event ) { return that._mouseUp( event ); }; this.document .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); event.preventDefault(); mouseHandled = true; return true; }, _mouseMove: function( event ) { //随着鼠标移动反复执行 // 怎样判断ie中鼠标越出文档范围,以及safari的跨iframe拖拽的问题??? // Only check for mouseups outside the document if you've moved inside the document // at least once. This prevents the firing of mouseup in the case of IE<9, which will // fire a mousemove event if content is placed under the cursor. See #7778 // Support: IE <9 if ( this._mouseMoved ) { // IE mouseup check - mouseup happened when mouse was out of window // documentMode文档兼容模式,低版本中没有,判断ie渲染页面的方式,也即ie的版本 // event.button判断鼠标按键,ie9开始和标准浏览器相同,左键为0,中键为1,右键为2,ie8左键为1,中键为4,右键为2 if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button ) { return this._mouseUp( event ); // Iframe mouseup check - mouseup occurred in another document } else if ( !event.which ) { // Support: Safari <=8 - 9 // Safari sets which to 0 if you press any of the following keys // during a drag (#14461) // event.originalEvent保存了浏览器原生事件对象,是jquery的机制,altkey指alt键被点击且保持状态 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || event.originalEvent.metaKey || event.originalEvent.shiftKey ) { this.ignoreMissingWhich = true; } else if ( !this.ignoreMissingWhich ) { return this._mouseUp( event ); } } } // event.which鼠标左键值为1,中键为2,右键为3,没有按鼠标为0,mouseDown函数中有要求event.which为1??? if ( event.which || event.button ) { this._mouseMoved = true; } // 鼠标未松开时第二次移动时,_mouseStarted和_mouseMoved记录在案,方便调用 if ( this._mouseStarted ) { this._mouseDrag( event ); return event.preventDefault(); } // 移动距离、延迟时间合乎规范的时候调用mouseStart和mouseDrag函数,延迟时间从鼠标按下时计时,定时mouseDelayMet变为真 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { this._mouseStarted = ( this._mouseStart( this._mouseDownEvent, event ) !== false ); ( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) ); } return !this._mouseStarted; }, _mouseUp: function( event ) { this.document .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); if ( this._mouseStarted ) { this._mouseStarted = false; // 鼠标按下又松开的事件,没有向文档节点绑定事件,mouseDown和mouseUp事件中的事件元素相同,鼠标移动事件绑定了文档节点 if ( event.target === this._mouseDownEvent.target ) { $.data( event.target, this.widgetName + ".preventClickEvent", true ); } this._mouseStop( event ); } if ( this._mouseDelayTimer ) { clearTimeout( this._mouseDelayTimer ); delete this._mouseDelayTimer; } this.ignoreMissingWhich = false; mouseHandled = false; event.preventDefault(); }, // 当前事件的坐标和鼠标按下时的坐标相比较得出水平及垂直距离 _mouseDistanceMet: function( event ) { return ( Math.max( Math.abs( this._mouseDownEvent.pageX - event.pageX ), Math.abs( this._mouseDownEvent.pageY - event.pageY ) ) >= this.options.distance ); }, _mouseDelayMet: function( /* event */ ) { return this.mouseDelayMet; }, // _mouseCapture决定交互是否应该基于交互的事件目标开始,返回为否的时候禁用交互事件 // _mouseStart处理交互的开始,_mouseDrag处理鼠标移动事件,_mouseStop交互的结束 _mouseStart: function( /* event */ ) {}, _mouseDrag: function( /* event */ ) {}, _mouseStop: function( /* event */ ) {}, _mouseCapture: function( /* event */ ) { return true; } } ); } ) );
相关推荐
- **js**:这个目录包含了 jQuery UI 的 JavaScript 文件,包括主库和各个组件的实现。 - **css**:这里存放了 CSS 样式文件,用于定义组件的外观。 综上所述,jQuery UI 1.8.16 是一个强大的工具,它提供了一套...
jQuery UI 1.7.2 是一个广泛使用的开源库,它基于 jQuery JavaScript 库,为开发人员提供了丰富的用户界面组件和交互功能。这个版本是 jQuery UI 的一个重要里程碑,它在1.x系列中引入了诸多改进和新特性,旨在提升...
`js` 文件夹存放 JavaScript 文件,其中 `ui/jquery.ui.core.js` 是核心模块,其他如 `ui/jquery.ui.widget.js`、`ui/jquery.ui.mouse.js` 等则为各个组件的具体实现;`css` 文件夹包含样式表,用于定义组件的视觉...
《jQuery JS源码解析与应用探索》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了JavaScript的DOM操作、事件处理、动画设计以及Ajax交互。它以其简洁的API和高效的性能,成为了网页开发者的首选工具。本...
需要`jquery.dimensions.js`,`ui.mouse.js`,`ui.draggable.js`,`ui.droppable.js`和`ui.sortable.js`。通过`$("#myList").sortable();`使列表项可以排序。可以调整元素间距、连接排序列表等,具体选项参见...
- jQuery UI:提供各种可交互的UI组件。 - Bootstrap:基于jQuery的前端框架,简化网页布局和设计。 - DataTables:增强HTML表格功能的插件。 **代码片段示例** 在"jquery-code-segment-master"中,可能包含了各种...
jQuery是一款广泛应用于Web开发的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画设计和Ajax交互。本资源“jQuery入门源码”旨在帮助初学者快速掌握jQuery的基本用法和核心概念。 1. **jQuery...
6. **插件**:jQuery 社区提供了众多高质量插件,如 DataTables 用于表格增强,Bootstrap 提供 UI 设计框架,JQueryUI 提供更丰富的用户界面组件。 离线文档和在线文档系统的存在,使得无论是在开发环境还是在生产...
`jquery-1.3.1.js`是核心库文件,`jquery-1.3.1-release.zip`则是完整包,包含了源码和其他资源。请注意,随着版本的更新,jQuery的功能和API可能会有所变化,建议使用最新稳定版以获取最佳性能和兼容性。 总之,...
**jQuery基础教程源码详解** jQuery,一个轻量级、高性能的JavaScript库,极大地简化了JavaScript的DOM操作、事件处理、动画制作以及Ajax交互。它以其简洁的API和高效的性能,成为了Web开发中的首选工具之一。本...
包含英文和中文两个版本附有本书源码. Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii 1. Introduction...
这个系统基于`jquery.1.10.2.min.js`,这是一个非常流行的轻量级JavaScript库,提供了丰富的DOM操作、事件处理和动画功能,简化了前端开发工作。 在这个系统中,用户可以通过鼠标悬停在不同的表情上预览他们的选择...
1. **jquery-1.7.2.js**:这是jQuery 1.7.2的完整源码文件,开发者可以查看其内部实现,理解其工作原理。 2. **jquery-1.6.4-vsdoc.js**:这是一个针对Visual Studio的文档文件,包含了1.6.4版本的API注释,对于使用...
jQuery是一个高效、简洁且功能强大的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画设计以及Ajax交互。下面,我们将深入探讨这些实例源码中涉及的知识点。 1. **DOM操作**:jQuery的核心之一是...
3. `js` - 这个目录可能包含了 jQuery 核心库和 jQuery UI 库的 JavaScript 文件。jQuery 是一个广泛使用的 JavaScript 库,简化了 DOM 操作、事件处理、动画和Ajax交互。jQuery UI 库则在 jQuery 基础上扩展了各种...
jQuery 社区提供了大量插件,如Bootstrap、jQuery UI等,它们扩展了jQuery的功能,例如日期选择器、滑块、轮播图等。开发者也可以根据需要编写自己的插件。 ## 五、jQuery源码分析 对于深入学习,查看和理解jQuery...
jQuery,作为一款广泛应用于Web开发的JavaScript库,以其简洁的API、强大的选择器和丰富的插件系统,极大地提高了前端开发效率。"锋利的jQuery实例源码"是一份集合了各种实用jQuery技巧和案例的资源,旨在帮助开发者...
《锋利的jQuery第二版》是一本深入解析jQuery库的权威书籍,其源码提供了丰富的实践示例和详细的实现细节,对于深入理解jQuery的工作机制及其应用具有极高的学习价值。以下将从多个方面详细阐述jQuery的相关知识点。...
jQuery提供了丰富的事件处理机制,如click、mouseover、mouseout等,使得用户在浏览商品、添加到购物车、查看详情等操作时能够得到即时反馈。例如,当用户点击某个商品图片时,可以使用$.ajax()方法加载商品详情,...
Dialogs.js可能就是一个自定义对话框插件,扩展了默认的jQuery UI功能。 8. **代码组织和效率**:jQuery通过链式调用来提高代码的可读性和效率,例如`$("#element").addClass("highlight").css("color", "red")`。 ...