Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitce60d31

Browse files
mgolgibson042
andauthored
Event: Simulate focus/blur in IE via focusin/focusout
In IE (all versions), `focus` & `blur` handlers are fired asynchronouslybut `focusin` & `focusout` are run synchronously. In other browsers, allthose handlers are fired synchronously. Asynchronous behavior of thesehandlers in IE caused issues for IE (gh-4856,gh-4859).We now simulate `focus` via `focusin` & `blur` via `focusout` in IE to avoidthese issues. This also let us simplify some tests.This commit also simplifies `leverageNative` - with IE now using `focusin`to simulate `focus` and `focusout` to simulate `blur`, we don't have to dealwith async events in `leverageNative`. This also fixes broken `focus` triggersafter first triggering it on a hidden element - previously, `leverageNative`assumed that the native `focus` handler not firing after calling the native `focus` method meant it would be handled later, asynchronously, whichwas not the case (gh-4950).Fixesgh-4856Fixesgh-4859Fixesgh-4950Closesgh-5223Co-authored-by: Richard Gibson <richard.gibson@gmail.com>
1 parent992a191 commitce60d31

File tree

2 files changed

+258
-166
lines changed

2 files changed

+258
-166
lines changed

‎src/event.js

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
importjQueryfrom"./core.js";
2-
importdocumentfrom"./var/document.js";
32
importdocumentElementfrom"./var/documentElement.js";
43
importrnothtmlwhitefrom"./var/rnothtmlwhite.js";
54
importrcheckableTypefrom"./var/rcheckableType.js";
65
importslicefrom"./var/slice.js";
6+
importisIEfrom"./var/isIE.js";
77
importacceptDatafrom"./data/var/acceptData.js";
88
importdataPrivfrom"./data/var/dataPriv.js";
99
importnodeNamefrom"./core/nodeName.js";
@@ -21,16 +21,6 @@ function returnFalse() {
2121
returnfalse;
2222
}
2323

24-
// Support: IE <=9 - 11+
25-
// focus() and blur() are asynchronous, except when they are no-op.
26-
// So expect focus to be synchronous when the element is already active,
27-
// and blur to be synchronous when the element is not already active.
28-
// (focus and blur are always synchronous in other supported browsers,
29-
// this just defines when we can count on it).
30-
functionexpectSync(elem,type){
31-
return(elem===document.activeElement)===(type==="focus");
32-
}
33-
3424
functionon(elem,types,selector,data,fn,one){
3525
varorigFn,type;
3626

@@ -459,7 +449,7 @@ jQuery.event = {
459449
el.click&&nodeName(el,"input")){
460450

461451
// dataPriv.set( el, "click", ... )
462-
leverageNative(el,"click",returnTrue);
452+
leverageNative(el,"click",true);
463453
}
464454

465455
// Return false to allow normal processing in the caller
@@ -511,10 +501,10 @@ jQuery.event = {
511501
// synthetic events by interrupting progress until reinvoked in response to
512502
// *native* events that it fires directly, ensuring that state changes have
513503
// already occurred before other listeners are invoked.
514-
functionleverageNative(el,type,expectSync){
504+
functionleverageNative(el,type,isSetup){
515505

516-
// MissingexpectSync indicates a trigger call, which must force setup through jQuery.event.add
517-
if(!expectSync){
506+
// Missing`isSetup` indicates a trigger call, which must force setup through jQuery.event.add
507+
if(!isSetup){
518508
if(dataPriv.get(el,type)===undefined){
519509
jQuery.event.add(el,type,returnTrue);
520510
}
@@ -526,15 +516,13 @@ function leverageNative( el, type, expectSync ) {
526516
jQuery.event.add(el,type,{
527517
namespace:false,
528518
handler:function(event){
529-
varnotAsync,result,
519+
varresult,
530520
saved=dataPriv.get(this,type);
531521

532522
if((event.isTrigger&1)&&this[type]){
533523

534524
// Interrupt processing of the outer synthetic .trigger()ed event
535-
// Saved data should be false in such cases, but might be a leftover capture object
536-
// from an async native handler (gh-4350)
537-
if(!saved.length){
525+
if(!saved){
538526

539527
// Store arguments for use when handling the inner native event
540528
// There will always be at least one argument (an event object), so this array
@@ -543,28 +531,17 @@ function leverageNative( el, type, expectSync ) {
543531
dataPriv.set(this,type,saved);
544532

545533
// Trigger the native event and capture its result
546-
// Support: IE <=9 - 11+
547-
// focus() and blur() are asynchronous
548-
notAsync=expectSync(this,type);
549534
this[type]();
550535
result=dataPriv.get(this,type);
551-
if(saved!==result||notAsync){
552-
dataPriv.set(this,type,false);
553-
}else{
554-
result={};
555-
}
536+
dataPriv.set(this,type,false);
537+
556538
if(saved!==result){
557539

558540
// Cancel the outer synthetic event
559541
event.stopImmediatePropagation();
560542
event.preventDefault();
561543

562-
// Support: Chrome 86+
563-
// In Chrome, if an element having a focusout handler is blurred by
564-
// clicking outside of it, it invokes the handler synchronously. If
565-
// that handler calls `.remove()` on the element, the data is cleared,
566-
// leaving `result` undefined. We need to guard against this.
567-
returnresult&&result.value;
544+
returnresult;
568545
}
569546

570547
// If this is an inner synthetic event for an event with a bubbling surrogate
@@ -582,16 +559,11 @@ function leverageNative( el, type, expectSync ) {
582559
}elseif(saved.length){
583560

584561
// ...and capture the result
585-
dataPriv.set(this,type,{
586-
value:jQuery.event.trigger(
587-
588-
// Support: IE <=9 - 11+
589-
// Extend with the prototype to reset the above stopImmediatePropagation()
590-
jQuery.extend(saved[0],jQuery.Event.prototype),
591-
saved.slice(1),
592-
this
593-
)
594-
});
562+
dataPriv.set(this,type,jQuery.event.trigger(
563+
saved[0],
564+
saved.slice(1),
565+
this
566+
));
595567

596568
// Abort handling of the native event
597569
event.stopImmediatePropagation();
@@ -724,6 +696,29 @@ jQuery.each( {
724696
},jQuery.event.addProp);
725697

726698
jQuery.each({focus:"focusin",blur:"focusout"},function(type,delegateType){
699+
700+
// Support: IE 11+
701+
// Attach a single focusin/focusout handler on the document while someone wants focus/blur.
702+
// This is because the former are synchronous in IE while the latter are async. In other
703+
// browsers, all those handlers are invoked synchronously.
704+
functionfocusMappedHandler(nativeEvent){
705+
706+
// `eventHandle` would already wrap the event, but we need to change the `type` here.
707+
varevent=jQuery.event.fix(nativeEvent);
708+
event.type=nativeEvent.type==="focusin" ?"focus" :"blur";
709+
event.isSimulated=true;
710+
711+
// focus/blur don't bubble while focusin/focusout do; simulate the former by only
712+
// invoking the handler at the lower level.
713+
if(event.target===event.currentTarget){
714+
715+
// The setup part calls `leverageNative`, which, in turn, calls
716+
// `jQuery.event.add`, so event handle will already have been set
717+
// by this point.
718+
dataPriv.get(this,"handle")(event);
719+
}
720+
}
721+
727722
jQuery.event.special[type]={
728723

729724
// Utilize native event if possible so blur/focus sequence is correct
@@ -732,10 +727,15 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp
732727
// Claim the first handler
733728
// dataPriv.set( this, "focus", ... )
734729
// dataPriv.set( this, "blur", ... )
735-
leverageNative(this,type,expectSync);
730+
leverageNative(this,type,true);
731+
732+
if(isIE){
733+
this.addEventListener(delegateType,focusMappedHandler);
734+
}else{
736735

737-
// Return false to allow normal processing in the caller
738-
returnfalse;
736+
// Return false to allow normal processing in the caller
737+
returnfalse;
738+
}
739739
},
740740
trigger:function(){
741741

@@ -746,6 +746,16 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp
746746
returntrue;
747747
},
748748

749+
teardown:function(){
750+
if(isIE){
751+
this.removeEventListener(delegateType,focusMappedHandler);
752+
}else{
753+
754+
// Return false to indicate standard teardown should be applied
755+
returnfalse;
756+
}
757+
},
758+
749759
// Suppress native focus or blur if we're currently inside
750760
// a leveraged native-event stack
751761
_default:function(event){

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp