🌐 AI搜索 & 代理 主页
Skip to content

Commit 5dc6b7c

Browse files
Alexander Farkasjeresig
authored andcommitted
Used the patch from Alexander as the basis for a rewrite of the IE change event logic. Now has full parity with the regular change event in other browsers: Works with regular bind, works better with multiple selects, works as a regular change event (note test suite changes), works with readonly/disabled inputs, and much more. The original patch had a number of problems, including firing the change event too many times, not bubblinb properly, and not handling clicks on multi-selects properly - that should all be fixed now. Thanks Alexander for the patch pushing in the right direction.
1 parent d7a0023 commit 5dc6b7c

File tree

3 files changed

+224
-167
lines changed

3 files changed

+224
-167
lines changed

src/event.js

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -612,65 +612,101 @@ jQuery.event.special.submit = {
612612
// change delegation, happens here so we have bind.
613613
if ( !jQuery.support.changeBubbles ) {
614614

615-
jQuery.event.special.change = {
616-
filters: {
617-
click: function( e ) {
618-
var elem = e.target;
615+
var formElems = /textarea|input|select/i;
619616

620-
if ( elem.nodeName.toLowerCase() === "input" && elem.type === "checkbox" ) {
621-
return trigger( "change", this, arguments );
622-
}
617+
function getVal( elem ) {
618+
var type = elem.type, val = elem.value;
623619

624-
return changeFilters.keyup.call( this, e );
625-
},
626-
keyup: function( e ) {
627-
var elem = e.target, data, index = elem.selectedIndex + "";
620+
if ( type === "radio" || type === "checkbox" ) {
621+
val = elem.checked;
628622

629-
if ( elem.nodeName.toLowerCase() === "select" ) {
630-
data = jQuery.data( elem, "_change_data" );
631-
jQuery.data( elem, "_change_data", index );
623+
} else if ( type === "select-multiple" ) {
624+
val = elem.selectedIndex > -1 ?
625+
jQuery.map( elem.options, function( elem ) {
626+
return elem.selected;
627+
}).join("-") :
628+
"";
632629

633-
if ( (elem.type === "select-multiple" || data != null) && data !== index ) {
634-
return trigger( "change", this, arguments );
635-
}
636-
}
637-
},
638-
beforeactivate: function( e ) {
639-
var elem = e.target;
630+
} else if ( elem.nodeName.toLowerCase() === "select" ) {
631+
val = elem.selectedIndex;
632+
}
633+
634+
return val;
635+
}
636+
637+
function testChange( e ) {
638+
var elem = e.target, data, val;
639+
640+
if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
641+
return;
642+
}
643+
644+
data = jQuery.data( elem, "_change_data" );
645+
val = getVal(elem);
640646

641-
if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" && !elem.checked ) {
642-
return trigger( "change", this, arguments );
647+
if ( val === data ) {
648+
return;
649+
}
650+
651+
// the current data will be also retrieved by beforeactivate
652+
if ( e.type !== "focusout" || elem.type !== "radio" ) {
653+
jQuery.data( elem, "_change_data", val );
654+
}
655+
656+
if ( elem.type !== "select" && (data != null || val) ) {
657+
e.type = "change";
658+
return jQuery.event.trigger( e, arguments[1], this );
659+
}
660+
}
661+
662+
jQuery.event.special.change = {
663+
filters: {
664+
focusout: testChange,
665+
666+
click: function( e ) {
667+
var elem = e.target, type = elem.type;
668+
669+
if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
670+
return testChange.call( this, e );
643671
}
644672
},
645-
blur: function( e ) {
646-
var elem = e.target, nodeName = elem.nodeName.toLowerCase();
647673

648-
if ( (nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password")))
649-
&& jQuery.data(elem, "_change_data") !== elem.value ) {
674+
// Change has to be called before submit
675+
// Keydown will be called before keypress, wich is used in submit-event delegation
676+
keydown: function( e ) {
677+
var elem = e.target, type = elem.type;
650678

651-
return trigger( "change", this, arguments );
679+
if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
680+
(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
681+
type === "select-multiple" ) {
682+
return testChange.call( this, e );
652683
}
653684
},
654-
focus: function( e ) {
655-
var elem = e.target, nodeName = elem.nodeName.toLowerCase();
656685

657-
if ( nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password" ) ) ) {
658-
jQuery.data( elem, "_change_data", elem.value );
686+
// Beforeactivate happens also before the previous element is blurred
687+
// with this event you can't trigger a change event, but you can store
688+
// information/focus[in] is not needed anymore
689+
beforeactivate: function( e ) {
690+
var elem = e.target;
691+
692+
if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
693+
return jQuery.data( elem, "_change_data", getVal(elem) );
659694
}
660695
}
661696
},
662697
setup: function( data, namespaces, fn ) {
663698
for ( var type in changeFilters ) {
664699
jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
665700
}
666-
667-
// always want to listen for change for trigger
668-
return false;
701+
702+
return formElems.test( this.nodeName );
669703
},
670704
remove: function( namespaces, fn ) {
671705
for ( var type in changeFilters ) {
672706
jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
673707
}
708+
709+
return formElems.test( this.nodeName );
674710
}
675711
};
676712

0 commit comments

Comments
 (0)