JQuery-1.9.1 source code analysis series (10) Event System Event packaging, jquery-1.9.1 source code
In the previous article to introduce you to the jQuery-1.9.1 source code analysis series (10) Event System of the Event System architecture, this article continues to introduce you to the jquery1.9.1 source code analysis series related knowledge, the specific content please see below.
First, you need to understand that the browser's native events are read-only, which limits jQuery's operations on them. A simple example shows why jQuery has to construct a new event object.
During delegation, node a entrusts Node B to execute the fn function when node a is clicked. When the event bubbles to Node B, the context environment must be correct when the fn is executed, that is, node a executes fn rather than Node B. How to ensure that the Context Environment for executing fn is a node: view the source code (red part)
// Execute ret = (jQuery. event. special [handleObj. origType] | |{}). handle | handleObj. handler). apply (matched. elem, args );
Use apply to replace the context of the execution function with node a (matched. elem ). Another point is that args [0] is the event object event. How can we ensure that the event is an event of node? This is the function of event. currentTarget, which is an important attribute. Therefore, we have performed one step before applying.
event.currentTarget = matched.elem;
Directly change the currentTarget attribute of the event object, which cannot be done in local browser events. Therefore, jQuery event objects are constructed based on local events.
There are two types of events: mouse events and Keyboard Events (you do not know when a touch event can be added ). Take a look at the detailed attributes of the two
Some of them are browser-based, not W3C standard. JQuery divides event attributes into three parts
JQuery. event. props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which". split ("")
JQuery. event. keyHooks. props: "char charCode key keyCode". split ("")
JQuery. event. mouseHooks. props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement". split ("")
A. construct a new event object jQuery. event. fix (originalEvent)
Construct a new event object in three steps
Step 1: Use event = new jQuery. event (originalEvent) to construct a new Event object (Click here if you do not understand the role of new ), add isDefaultPrevented, originalEvent, type, timeStamp, and modified tags to create an event (optimized for use to avoid unnecessary processing ). The source code of jQuery. Event (src, props) is as follows:
JQuery. Event = function (src, props) {// Allow instantiation without the 'new' keyword if (! (This instanceof jQuery. event) {return new jQuery. event (src, props);} // src is the Event object if (src & src. type) {this. originalEvent = src; this. type = src. type; // The document for event bubbling may be marked as blocking the occurrence of default events; this function can reflect the correct value of the flag for blocking this. isDefaultPrevented = (src. defaultPrevented | src. returnValue = false | src. getPreventDefault & src. getPreventDefault ())? ReturnTrue: returnFalse; // src is the event type} else {this. type = src;} // Add the explicitly provided features to the event object if (props) {jQuery. extend (this, props);} // create a timestamp if the input event contains more than one this. timeStamp = src & src. timeStamp | jQuery. now (); // The flag event has fixed this [jQuery. expando] = true ;};
The event object created in step 1
Step 2: Identify the event type and copy the corresponding attributes from the local originalEvent of the browser.
// Create a copy of The writable event object and format some feature names var I, prop, copy, type = event. type, originalEvent = event, fixHook = this. fixHooks [type]; if (! FixHook) {this. fixHooks [type] = fixHook = // rmouseEvent =/^ (? : Mouse | contextmenu) | click/rmouseEvent. test (type )? This. mouseHooks: // rkeyEvent =/^ key/rkeyEvent. test (type )? This. keyHooks: {};} // obtain the attribute list copy = fixHook. props from the native event? This. props. concat (fixHook. props): this. props ;... // copy all native attributes to the new event. length; while (I --) {prop = copy [I]; event [prop] = originalEvent [prop];}
Step 3: compatible processing of related attributes
// IE <9 corrected the target feature value if (! Event.tar get) {event.tar get = originalEvent. srcElement | document;} // Chrome 23 +, Safari ?, The Target feature value cannot be a text node if (event.tar get. nodeType = 3) {event.tar get = event.tar get. parentNode;} // IE <9. For mouse/Keyboard Events, if metaKey is not defined, set metaKey = false event. metaKey = !! Event. metaKey; // call the hooks filter return fixHook. filter? FixHook. filter (event, originalEvent): event;
The last code is compatible with mouse events and Keyboard Events.
FixHook. filter may be jQuery. event. keyHooks. filter
KeyHooks. filter: function (event, original) {// Add the which feature value to the keyboard event if (event. which = null) {event. which = original. charCode! = Null? Original. charCode: original. keyCode;} return event ;}
Or this jQuery. event. mouseHooks. filter
MouseHooks. filter: function (event, original) {var body, eventDoc, doc, button = original. button, fromElement = original. fromElement; // if the event pageX/Y feature is missing, use the available clientX/Y to calculate if (event. pageX = null & original. clientX! = Null) {eventDoc = event.tar get. ownerDocument | document; doc = eventDoc.doc umentElement; body = eventDoc. body; event. pageX = original. clientX + (doc & doc. scrollLeft | body & body. scrollLeft | 0)-(doc & doc. clientLeft | body & body. clientLeft | 0); event. pageY = original. clientY + (doc & doc. scrollTop | body & body. scrollTop | 0)-(doc & doc. clientTop | body & body. cli EntTop | 0);} // Add the relatedTarget feature if (! Event. relatedTarget & fromElement) {event. relatedTarget = fromElement = event.tar get? Original. toElement: fromElement;} // Add click event which feature value: 1 = left; 2 = middle; 3 = right // remarks: button is not standard, therefore, do not use if (! Event. which & button! = Undefined) {event. which = (button & 1? 1: (button & 2? 3: (button & 4? 2: 0);} return event ;}
The latest event object after the build is as follows (take the mouse event as an example)
Native events are saved in originalEvent, and target stores the target node (delegated node and event source). Other information is skipped.
B. Overload event Methods
When building a new event object Event = new jQuery. event (originalEvent), the event inherits the method in jQuery. Event. prototype. Let's take a look at the methods
The previous analysis of jQuery. event. prototype overload the stopPropagation method: in addition to calling the event object blocking bubble method, prototype also plays a role in the process of multiple delegated events waiting for processing on the delegated node, one of the events calls the event. stopPropagation () will prevent subsequent event processing. Click here to search for keywords to view
The preventDefault function also plays a similar role. This code is added to the preventDefault function.
this.isPropagationStopped = returnTrue;
In the trigger event function and simulate the bubble simulate function, the isPropagationStopped () function determines whether to perform the default operations on the DOM node. The source code is as follows:
IsImmediatePropagationStopped is a special usage of stopPropagation. isImmediatePropagationStopped directly blocks the current processing and subsequent event processing. stopPropagation then stops the subsequent event processing.
The source code is as follows:
// JQuery. event is bound based on the ECMAScript language specified by the DOM Event // http://www.w.org/TR//WD-DOM-Level--Events-/ecma-script-binding.htmljQuery.Event.prototype = {isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, preventDefault: function. originalEvent; this. isDefaultPrevented = returnTrue; if (! E) {return;} if (e. preventDefault) {e. preventDefault (); // IE support} else {e. returnValue = false ;}}, stopPropagation: function () {var e = this. originalEvent; this. isPropagationStopped = returnTrue; if (! E) {return;} if (e. stopPropagation) {e. stopPropagation ();} // IE supports e. cancelBubble = true;}, stopImmediatePropagation: function () {this. isImmediatePropagationStopped = returnTrue; this. stopPropagation ();}}
The above is the jQuery-1.9.1 source code analysis series (10) Event System Event packaging, hope you like.