@@ -4,14 +4,15 @@ define( [
4
4
"./var/documentElement" ,
5
5
"./var/isFunction" ,
6
6
"./var/rnothtmlwhite" ,
7
+ "./var/rcheckableType" ,
7
8
"./var/slice" ,
8
9
"./data/var/dataPriv" ,
9
10
"./core/nodeName" ,
10
11
11
12
"./core/init" ,
12
13
"./selector"
13
14
] , function ( jQuery , document , documentElement , isFunction , rnothtmlwhite ,
14
- slice , dataPriv , nodeName ) {
15
+ rcheckableType , slice , dataPriv , nodeName ) {
15
16
16
17
"use strict" ;
17
18
@@ -329,9 +330,10 @@ jQuery.event = {
329
330
while ( ( handleObj = matched . handlers [ j ++ ] ) &&
330
331
! event . isImmediatePropagationStopped ( ) ) {
331
332
332
- // Triggered event must either 1) have no namespace, or 2) have namespace(s)
333
- // a subset or equal to those in the bound event (both can have no namespace).
334
- if ( ! event . rnamespace || event . rnamespace . test ( handleObj . namespace ) ) {
333
+ // If the event is namespaced, then each handler is only invoked if it is
334
+ // specially universal or its namespaces are a superset of the event's.
335
+ if ( ! event . rnamespace || handleObj . namespace === false ||
336
+ event . rnamespace . test ( handleObj . namespace ) ) {
335
337
336
338
event . handleObj = handleObj ;
337
339
event . data = handleObj . data ;
@@ -457,37 +459,101 @@ jQuery.event = {
457
459
} ,
458
460
focus : {
459
461
460
- // Fire native event if possible so blur/focus sequence is correct
462
+ // Utilize native event if possible so blur/focus sequence is correct
463
+ setup : function ( ) {
464
+
465
+ // Claim the first handler
466
+ // dataPriv.set( this, "focus", ... )
467
+ leverageNative ( this , "focus" , false , function ( el ) {
468
+ return el !== safeActiveElement ( ) ;
469
+ } ) ;
470
+
471
+ // Return false to allow normal processing in the caller
472
+ return false ;
473
+ } ,
461
474
trigger : function ( ) {
462
- if ( this !== safeActiveElement ( ) && this . focus ) {
463
- this . focus ( ) ;
464
- return false ;
465
- }
475
+
476
+ // Force setup before trigger
477
+ leverageNative ( this , "focus" , returnTrue ) ;
478
+
479
+ // Return non-false to allow normal event-path propagation
480
+ return true ;
466
481
} ,
482
+
467
483
delegateType : "focusin"
468
484
} ,
469
485
blur : {
486
+
487
+ // Utilize native event if possible so blur/focus sequence is correct
488
+ setup : function ( ) {
489
+
490
+ // Claim the first handler
491
+ // dataPriv.set( this, "blur", ... )
492
+ leverageNative ( this , "blur" , false , function ( el ) {
493
+ return el === safeActiveElement ( ) ;
494
+ } ) ;
495
+
496
+ // Return false to allow normal processing in the caller
497
+ return false ;
498
+ } ,
470
499
trigger : function ( ) {
471
- if ( this === safeActiveElement ( ) && this . blur ) {
472
- this . blur ( ) ;
473
- return false ;
474
- }
500
+
501
+ // Force setup before trigger
502
+ leverageNative ( this , "blur" , returnTrue ) ;
503
+
504
+ // Return non-false to allow normal event-path propagation
505
+ return true ;
475
506
} ,
507
+
476
508
delegateType : "focusout"
477
509
} ,
478
510
click : {
479
511
480
- // For checkbox, fire native event so checked state will be right
481
- trigger : function ( ) {
482
- if ( this . type === "checkbox" && this . click && nodeName ( this , "input" ) ) {
483
- this . click ( ) ;
484
- return false ;
512
+ // Utilize native event to ensure correct state for checkable inputs
513
+ setup : function ( data ) {
514
+
515
+ // For mutual compressibility with _default, replace `this` access with a local var.
516
+ // `|| data` is dead code meant only to preserve the variable through minification.
517
+ var el = this || data ;
518
+
519
+ // Claim the first handler
520
+ if ( rcheckableType . test ( el . type ) &&
521
+ el . click && nodeName ( el , "input" ) &&
522
+ dataPriv . get ( el , "click" ) === undefined ) {
523
+
524
+ // dataPriv.set( el, "click", ... )
525
+ leverageNative ( el , "click" , false , returnFalse ) ;
485
526
}
527
+
528
+ // Return false to allow normal processing in the caller
529
+ return false ;
530
+ } ,
531
+ trigger : function ( data ) {
532
+
533
+ // For mutual compressibility with _default, replace `this` access with a local var.
534
+ // `|| data` is dead code meant only to preserve the variable through minification.
535
+ var el = this || data ;
536
+
537
+ // Force setup before triggering a click
538
+ if ( rcheckableType . test ( el . type ) &&
539
+ el . click && nodeName ( el , "input" ) &&
540
+ dataPriv . get ( el , "click" ) === undefined ) {
541
+
542
+ leverageNative ( el , "click" , returnTrue ) ;
543
+ }
544
+
545
+ // Return non-false to allow normal event-path propagation
546
+ return true ;
486
547
} ,
487
548
488
- // For cross-browser consistency, don't fire native .click() on links
549
+ // For cross-browser consistency, suppress native .click() on links
550
+ // Also prevent it if we're currently inside a leveraged native-event stack
489
551
_default : function ( event ) {
490
- return nodeName ( event . target , "a" ) ;
552
+ var target = event . target ;
553
+ return rcheckableType . test ( target . type ) &&
554
+ target . click && nodeName ( target , "input" ) &&
555
+ dataPriv . get ( target , "click" ) ||
556
+ nodeName ( target , "a" ) ;
491
557
}
492
558
} ,
493
559
@@ -504,6 +570,77 @@ jQuery.event = {
504
570
}
505
571
} ;
506
572
573
+ // Ensure the presence of an event listener that handles manually-triggered
574
+ // synthetic events by interrupting progress until reinvoked in response to
575
+ // *native* events that it fires directly, ensuring that state changes have
576
+ // already occurred before other listeners are invoked.
577
+ function leverageNative ( el , type , forceAdd , allowAsync ) {
578
+
579
+ // Setup must go through jQuery.event.add
580
+ if ( forceAdd ) {
581
+ jQuery . event . add ( el , type , forceAdd ) ;
582
+ return ;
583
+ }
584
+
585
+ // Register the controller as a special universal handler for all event namespaces
586
+ dataPriv . set ( el , type , forceAdd ) ;
587
+ jQuery . event . add ( el , type , {
588
+ namespace : false ,
589
+ handler : function ( event ) {
590
+ var maybeAsync , result ,
591
+ saved = dataPriv . get ( this , type ) ;
592
+
593
+ // Interrupt processing of the outer synthetic .trigger()ed event
594
+ if ( ( event . isTrigger & 1 ) && this [ type ] && ! saved ) {
595
+
596
+ // Store arguments for use when handling the inner native event
597
+ saved = slice . call ( arguments ) ;
598
+ dataPriv . set ( this , type , saved ) ;
599
+
600
+ // Trigger the native event and capture its result
601
+ // Support: IE <=9 - 11+
602
+ // focus() and blur() are asynchronous
603
+ maybeAsync = allowAsync ( this , type ) ;
604
+ this [ type ] ( ) ;
605
+ result = dataPriv . get ( this , type ) ;
606
+ if ( result !== saved ) {
607
+ dataPriv . set ( this , type , false ) ;
608
+
609
+ // Cancel the outer synthetic event
610
+ event . stopImmediatePropagation ( ) ;
611
+ event . preventDefault ( ) ;
612
+ return result ;
613
+ } else if ( maybeAsync ) {
614
+
615
+ // Cancel the outer synthetic event in expectation of a followup
616
+ event . stopImmediatePropagation ( ) ;
617
+ event . preventDefault ( ) ;
618
+ return ;
619
+ } else {
620
+ dataPriv . set ( this , type , false ) ;
621
+ }
622
+
623
+ // If this is a native event triggered above, everything is now in order
624
+ // Fire an inner synthetic event with the original arguments
625
+ } else if ( ! event . isTrigger && saved ) {
626
+
627
+ // ...and capture the result
628
+ dataPriv . set ( this , type , jQuery . event . trigger (
629
+
630
+ // Support: IE <=9 - 11+
631
+ // Extend with the prototype to reset the above stopImmediatePropagation()
632
+ jQuery . extend ( saved . shift ( ) , jQuery . Event . prototype ) ,
633
+ saved ,
634
+ this
635
+ ) ) ;
636
+
637
+ // Abort handling of the native event
638
+ event . stopImmediatePropagation ( ) ;
639
+ }
640
+ }
641
+ } ) ;
642
+ }
643
+
507
644
jQuery . removeEvent = function ( elem , type , handle ) {
508
645
509
646
// This "if" is needed for plain objects
0 commit comments