Found a small point that had not been noticed before
Stoppropagation:function () {
var e = this.originalevent;
...
if (e.stoppropagation) {
e.stoppropagation ();
}
The Stoppropagation function of the local event object called by the jquery overload stoppropagation function blocks bubbling. In other words, the current node, not the event source, is blocked from bubbling.
When it comes to triggering events, our first reaction is to use $ (...). Click () This way triggers the Click event. There is no doubt that this approach is straightforward, if it is recommended in this way. But what if it's a custom event? For example, define a $ (document). On ("Chuaclick", "#middle", FN); How does this trigger an event? This will take $ ("#middle"). Trigger ("Chuaclick").
A. Triggering events low-api--jquery.event.trigger
The trigger function provides support for triggering all types of events. These events fall into two main categories: normal browser events (which include events with namespaces such as "Click.chua"), and custom events. The internal implementation of the function is not invoked because it is to be unified. Click () is a way to make shortcuts to ordinary browser events, but to unify the process. The processing process is as follows
1. Gets the event to be triggered (the incoming event may be an event type rather than an event object)
event = event[Jquery.expando]? Event:new jquery.event (type, typeof event = = "Object" && event);
2. Fix browser events (mainly with modified event source) and combination of correct event handling parameters data
if (Type.indexof (".") >= 0) {
//Event trigger with a namespace, the event-handler entry function handle () is used for the type
namespaces = Type.split (".").
type = Namespaces.shift ();
Namespaces.sort ();
}
...//Can the caller pass the Jquery.event object, the ordinary object, or even the string
event = event[Jquery.expando]?
Event:
new Jquery.event (type, typeof event = = "Object" && event);
Event.istrigger = true;
Event.namespace = Namespaces.join (".");
Event.namespace_re = event.namespace?
New RegExp ("(^|\\.)" + namespaces.join ("\. (?:. *\\.|)") + "(\\.| $) "):
null;
Resets the result property to avoid the last residual
event.result = undefined;
if (!event.target) {
event.target = elem;
}
To clone the parameter data and place the event before the reference data, create an argument list of the event-handling entry function, which may result in [event,data]
data = data = null?
[Event]:
jquery.makearray (data, [Event]);
The following combination event processing argument list data is called when processed later
if (handle) {
handle.apply (cur, data);
}
3. A special event that determines whether a particular node object is special
Special = jquery.event.special[Type] | | {};
if (!onlyhandlers && special.trigger && special.trigger.apply (elem, data) = = False) {return
;
}
There are fewer incidents that require special treatment here.
Special: {
click.trigger:function () { //checkbox, triggering local event to ensure correct state if (Jquery.nodename (this, "input") && t His.type = = "checkbox" && this.click) {
this.click ();
return false;
}
,
focus.trigger:function () { //triggers a local event to guarantee that the Defocus/focus sequence is correct if (this!== Document.activeelement && this.focus) {
try {
this.focus ();
return false;
} catch (E) {
//support:ie<9
//If We error on focus to hidden Element (#1486, #12518),
//Let. Trigge R () Run the Handlers
}
}
,
blur.trigger:function () {if (this = = Document.activeelement & & This.blur) {
this.blur ();
return false;
}
}
}
4. Start traversing the parent node from the event source until the Window object, save the passed node (save to Eventpath) and stand down
for (; cur; cur = cur.parentnode) {
eventpath.push (cur);
TMP = cur;
}
Press window also into eventpath (e.g., not normal object nor disconnected DOM)
if (tmp = = (Elem.ownerdocument | | document)) {
Eventpath.push (Tmp.defaultview | | tmp.parentwindow | | window);
}
5. Loop the previously saved node, access the node cache, and call out its bound event (entry function) if there is a corresponding event type processing queue.
JQuery binding function Processing: To determine whether the node cache to save the appropriate event handler functions, if there is the execution
handle = (Jquery._data (cur, "events") | | {}) [Event.type] && jquery._data (cur, "handle");
if (handle) {
handle.apply (cur, data);
}
Local binding processing
handle = Ontype && cur[ontype];
if (Handle && jquery.acceptdata (cur) && handle.apply && handle.apply (cur, data) = False) {
Event.preventdefault ();
}
6. Finally handle browser default events, such as submission form processing for submit tags.
If no one is blocking the default processing, the execution of
if (!onlyhandlers &&!event.isdefaultprevented ()) {
...
}
Note: Ordinary events plus namespaces still belong to ordinary events, and the normal invocation still works. such as $ (document). On (' Click.chua ', ' #id ', fn1). On ("click", "#id", fn2); Fn1 will still be invoked when clicking on the "#id" node. The only way to trigger the specified namespace event is trigger:$ ("#id"). Trigger ("Click.chua"), at which point only fn1 is invoked.
From the 4th and 5 steps you can see another huge effect of trigger--simulated bubbling processing. The following will analyze
B. Event special handling JQuery.event.special (main event substitution, simulation bubbling) detailed
The delegate design is based on events that can be bubbling. But some events are not bubbling, and some events support different bubbles in different browsers. There are also different types of events supported by browsers. These processes are mostly placed in jQuery.event.special. The JQuery.event.special object holds the variables and methods needed to fit a specific event.
Specifically:
Delegatetype/bindtype (for event type adjustment)
Setup (called at the time of the first binding of an event)
Add (called at event binding)
Remove (called at time of unblocking event binding)
Teardown (called when all event bindings are dismissed)
Trigger (called at time of Internal trigger event)
Nobubble
_default
Handle (called when the event is actually triggered)
Predispatch (called before actual triggering event)
Postdispatch (called after the event is actually triggered)
Take a look at the function that simulates bubbling simulate
Simulate:function (type, Elem, event, bubble) {
//Build a new event to distinguish between previously bound events.
The newly built event avoids bubbling, but if the impersonation event can block the default action, we do the same block default action.
var e = jquery.extend (
new Jquery.event (),
Event,
{type:type,
issimulated:true,
Originalevent: {}
}
);
if (bubble) {
JQuery.event.trigger (E, null, elem);
} else {
jQuery.event.dispatch.call (Elem, e);
}
if (e.isdefaultprevented ()) {
event.preventdefault ();
}
}
See no, really simulate bubble function is JQuery.event.trigger function
Special First Group
This involves the bubbling process.
Special: {load: {//Prevent triggering image.load event bubbling to Window.load nobubble:true}, click: {//checkbox is guaranteed to be in correct state when triggered Trigger:function () {if (...)
{This.click (); return false;}} Focus: {//trigger this current node Blur/focus event to ensure that the queue is correct trigger:function () {if (This!== document.activeelement && Amp
This.focus) {try {this.focus ();
return false;
catch (E) {//ie<9, if we mistakenly let the hidden node get the focus (#1486, #12518),//Let. Trigger () run the processor} }, Delegatetype: "Focusin"}, Blur: {trigger:function () {if (this = = Document.activeelement && Amp
This.blur) {This.blur ();
return false; }, Delegatetype: "Focusout"}, Beforeunload: {postdispatch:function (event) {//even returnvalue, etc. The Undefined,firefox still displays a warning if (event.result!== undefined) {event.originalEvent.returnValue = Event.resul
T }
}
}
}
Focus/blur is not supposed to be bubbling, but we can still go through $ (document). On (' Focus ', ' #left ', FN) to bind, how do we do that? Let's see how jquery is handled.
In the first step, the focus-bound event is converted to Focusin to bind, Focusin is bubbling in the standard of the consortium, and the browser outside of Firefox does support bubbling (the Firefox browser focusin/focusout support bubbling compatibility will be detailed later)
Type = (selector special.delegateType:special.bindType) | | Type
The new special is then obtained based on the newly obtained type (focusin)
Special = jquery.event.special[Type] | | {};
The special result obtained is
Jquery.each ({focus: "Focusin", Blur: "Focusout"}, Function (orig, fix) {
var attaches = 0,
handler = Functi On (event) {
//simulate bubbling
jQuery.event.simulate (fix, Event.target, JQuery.event.fix (event), true);
};
jquery.event.special[fix] = {
setup:function () {
if (attaches++ = = 0) {
Document.addeventlistener (orig, Handler, True);
}
,
teardown:function () {
if (--attaches = 0) {
document.removeeventlist Ener (orig, Handler, true);
}
};
});
Then, is the binding event, binding events in fact on the Focusin, focusout do a compatible processing, the first source of judgment has Special.setup.call (... This code, when the first entry is visible according to the setup function above, is actually binding events through the Document.addeventlistener (orig, Handler, true) in the Setup function, noting that the first argument is orig, Because Firefox does not support Focusin/focusout, jquery uses Focus/blur instead to listen for events; Note that the third argument is true, indicating that the event was triggered during the event capture phase.
We know that any browser capture is from the outer layer to the exact node, all the Focusin events will be captured, and then execute the handler function (inside the JQuery.event.simulate function, the source code). Other event bindings Enter the IF branch to bind the event directly to the Elem
if (!special.setup | | special.setup.call (elem, data, namespaces, eventhandle) = = False) {
if (elem.addeventlis Tener) {
Elem.addeventlistener (type, eventhandle, false);
else if (elem.attachevent) {
elem.attachevent ("on" + Type, eventhandle);
}
}
Special Group II: Mouseenter/mouseleave
Create Mouseenter/leave event Jquery.each using Mouseover/out and event timing detection
({
mouseenter: "MouseOver",
MouseLeave: " Mouseout "
}, Function (orig, fix) {
jquery.event.special[orig] = {
Delegatetype:fix,
bindtype:fix,
handle:function (event) {
var ret,
target = this,
related = event.relatedtarget,
handleobj = even T.handleobj;
For Mousenter/leave, the handler/reference is invoked when related is outside target
: When the mouse leaves/enters the browser window there is no relatedtarget
if (! Related | | (Related!== target &&!jquery.contains (target, related)) {
event.type = Handleobj.origtype;
RET = handleObj.handler.apply (this, arguments);
event.type = fix;
}
return ret;
};
};
Note that the MouseEnter event is triggered only when the mouse pointer crosses the selected element. Corresponding mouseleave in this way, mouseenter elements do not repeatedly trigger events, otherwise, in IE, there is often flicker occurs
Using Mouseover/out and event timing detection to create a Mouseenter/leave event has a critical judgment
if (!related | | (Related!== target &&!jquery.contains (target, related))
Of these,!jquery.contains (target, related) indicates that related is outside target. We use the legend to explain
We assume that we are dealing with the MouseEnter event and entering target.
The mouse from related to target, obviously related outside target, so when the mouse moves to target, the condition is met and the call is processed.
Now, in turn, it is obvious that related is in target, then the mouse is in the MouseEnter state (which means that the MouseEnter processor has been processed before), and avoiding repeated calls is of course not directly returned without any processing.
We assume that the MouseLeave event is handled, leaving target.
Mouse from Target to related, obviously related in target, so when the mouse moved to the related still do not leave target, do not handle.
Mouse from Target to related, obviously related outside target, so when the mouse moved to related has left the target range, do processing.
Special Third Group: Submit and change
The main is IE under submit cannot bubble processing
JQuery.event.special.submit mainly has a few characteristics
Setup
Postdispatch
Teardown
Depending on the code that adds the event, when the event is added, Setup is invoked to add the event if it meets the criteria
if (!special.setup | | special.setup.call (elem, data, namespaces, eventhandle) = = False)
jquery simulates the submit event under IE to click and keypress instead, except to add namespaces to differentiate and normal click and KeyPress events.
Setup:function () {
...
JQuery.event.add (This, "Click._submit keypress._submit", function (e) {
var elem = e.target,
form = Jque Ry.nodename (Elem, "input") | | Jquery.nodename (Elem, "button")? elem.form:undefined;
if (Form &&!jquery._data (form, "Submitbubbles")) {
jQuery.event.add (form, "Submit._submit", func tion (event) {
event._submit_bubble = true;
});
Jquery._data (Form, "Submitbubbles", true);
}}
);
Postdispatch is invoked during the event invocation (dispatch) to process the
if (special.postdispatch) {
Special.postDispatch.call (this, event);
}
Postdispatch Simulate Completion event processing
postdispatch:function (event) {
//If form is submitted by the user, bubble the Event up of the tree
if (event._submit_bubble) {
delete event._submit_bubble;
if (This.parentnode &&!event.istrigger) {
jQuery.event.simulate ("Submit", This.parentnode, event, tr UE);
}
}
,
Teardown used in Delete event bindings
The processing of the change event in IE is similar to that of submit, the event uses beforeactivate substitution to listen, the processing function becomes handle, executes the code in the event distribution (dispatch)
ret = ((jquery.event.special[Handleobj.origtype] | | {}). Handle | | Handleobj.handler)
. Apply (Matched.elem, args);
The main source code is as follows
JQuery.event.special.change = {setup:function () {//rformelems =/^ (?: Input|select|textarea) $/i if (Rformelems.test (this.nodename)) {//IE does not trigger the Change event before the Check/radio is lost; The Click event that triggers it after the property has changed//in spec
The change event triggered by the Ial.change.handle will be swallowed.//It will trigger the onchange event after the Check/radio is lost. if (This.type = = "checkbox" | | this.type = = "Radio") {JQuery.event.add (this, "Propertychange._change", F Unction (Event) {if (Event.originalEvent.propertyName = = "Checked") {This._just_change
D = true;
}
}); JQuery.event.add (This, "Click._change", function (event) {if (this._just_changed &&!event.istri
Gger) {this._just_changed = false; }//Allow triggered, simulated change events (#11500) jQuery.event.simulate (' Change ', this,
event, True);
}); } rEturn false; }//Event agent; Lazy mode adds change event handling to descendant input nodes JQuery.event.add (this, "Beforeactivate._change", function (e) {var elem =
E.target; if (Rformelems.test (elem.nodename) &&!jquery._data (Elem, "Changebubbles")) {JQuery.event.add ( Elem, "Change._change", function (event) {if (This.parentnode &&!event.issimulated &&!e
Vent.istrigger) {jQuery.event.simulate ("change", This.parentnode, event, true);
}
});
Jquery._data (Elem, "Changebubbles", true);
}
});
}, Handle:function (event) {var elem = Event.target; Swallow the Change event for the local Radio box and check box, we've already set out on top. Event if (this!== elem | | event.issimulated | | event.istrigger | | (Elem.type!== "Radio" && elem.type!== "checkbox"))
{return event.handleObj.handler.apply (this, arguments); } }, }
OK, to this, the event system also tells a paragraph, thank you for your support.