" ),
cb = markup.find( "input" )[ 0 ];
markup.appendTo( "#qunit-fixture" );
jQuery( cb ).on( "click", function() {
assert.equal( this.checked, false, "just-clicked checkbox is not checked" );
} );
markup.on( "click", function() {
assert.equal( cb.checked, false, "checkbox is not checked in bubbled event" );
} );
// Native click
cb.checked = true;
assert.equal( cb.checked, true, "native event - checkbox is initially checked" );
cb.click();
assert.equal( cb.checked, false, "native event - checkbox is no longer checked" );
// jQuery click
cb.checked = true;
assert.equal( cb.checked, true, "jQuery event - checkbox is initially checked" );
jQuery( cb ).trigger( "click" );
assert.equal( cb.checked, false, "jQuery event - checkbox is no longer checked" );
// Handlers only; checkbox state remains false
jQuery( cb ).triggerHandler( "click" );
assert.equal( cb.checked, false, "handlers only - checkbox is still unchecked" );
// Trigger parameters are preserved (trac-13353, gh-4139)
cb.checked = true;
assert.equal( cb.checked, true, "jQuery event with data - checkbox is initially checked" );
jQuery( cb ).on( "click", function( e, data ) {
assert.equal( data, "clicked", "trigger data passed to handler" );
} );
markup.on( "click", function( e, data ) {
assert.equal( data, "clicked", "trigger data passed to bubbled handler" );
} );
jQuery( cb ).trigger( "click", [ "clicked" ] );
assert.equal( cb.checked, false, "jQuery event with data - checkbox is no longer checked" );
} );
QUnit.test( "event object properties on natively-triggered event", function( assert ) {
assert.expect( 3 );
var link = document.createElement( "a" ),
$link = jQuery( link ),
evt = document.createEvent( "MouseEvents" );
// Support: IE <=9 - 11 only
// IE requires element to be in the body before it will dispatch
$link.appendTo( "body" ).on( "click", function( e ) {
// Not trying to assert specific values here, just ensure the property exists
assert.equal( "detail" in e, true, "has .detail" );
assert.equal( "cancelable" in e, true, "has .cancelable" );
assert.equal( "bubbles" in e, true, "has .bubbles" );
} );
evt.initEvent( "click", true, true );
link.dispatchEvent( evt );
$link.off( "click" ).remove();
} );
QUnit.test( "addProp extensions", function( assert ) {
assert.expect( 2 );
var $fixture = jQuery( "
" ).appendTo( "#qunit-fixture" );
// Ensure the property doesn't exist
$fixture.on( "click", function( event ) {
assert.ok( !( "testProperty" in event ), "event.testProperty does not exist" );
} );
fireNative( $fixture[ 0 ], "click" );
$fixture.off( "click" );
jQuery.event.addProp( "testProperty", function() { return 42; } );
// Trigger a native click and ensure the property is set
$fixture.on( "click", function( event ) {
assert.equal( event.testProperty, 42, "event.testProperty getter was invoked" );
} );
fireNative( $fixture[ 0 ], "click" );
$fixture.off( "click" );
$fixture.remove();
} );
QUnit.test( "drag/drop events copy mouse-related event properties (gh-1925, gh-2009)", function( assert ) {
assert.expect( 4 );
var $fixture = jQuery( "
" ).appendTo( "body" );
$fixture.on( "dragmove", function( evt ) {
assert.ok( "pageX" in evt, "checking for pageX property on dragmove" );
assert.ok( "pageY" in evt, "checking for pageY property on dragmove" );
} );
fireNative( $fixture[ 0 ], "dragmove" );
$fixture.on( "drop", function( evt ) {
assert.ok( "pageX" in evt, "checking for pageX property on drop" );
assert.ok( "pageY" in evt, "checking for pageY property on drop" );
} );
fireNative( $fixture[ 0 ], "drop" );
$fixture.off( "dragmove drop" ).remove();
} );
QUnit.test( "focusin using non-element targets", function( assert ) {
assert.expect( 2 );
jQuery( document ).on( "focusin", function( e ) {
assert.ok( e.type === "focusin", "got a focusin event on a document" );
} ).trigger( "focusin" ).off( "focusin" );
jQuery( window ).on( "focusin", function( e ) {
assert.ok( e.type === "focusin", "got a focusin event on a window" );
} ).trigger( "focusin" ).off( "focusin" );
} );
testIframe(
"focusin from an iframe",
"event/focusinCrossFrame.html",
function( assert, framejQuery, frameWin, frameDoc ) {
assert.expect( 1 );
var done = assert.async(),
focus = false,
input = jQuery( frameDoc ).find( "#frame-input" );
// Create a focusin handler on the parent; shouldn't affect the iframe's fate
jQuery( "body" ).on( "focusin.iframeTest", function() {
// Support: IE 9 - 11+
// IE does propagate the event to the parent document. In this test
// we mainly care about the inner element so we'll just skip this one
// assertion in IE.
if ( !document.documentMode ) {
assert.ok( false, "fired a focusin event in the parent document" );
}
} );
input.on( "focusin", function() {
focus = true;
assert.ok( true, "fired a focusin event in the iframe" );
} );
// Avoid a native event; Chrome can't force focus to another frame
input[ 0 ].focus();
// Remove body handler manually since it's outside the fixture
jQuery( "body" ).off( "focusin.iframeTest" );
setTimeout( function() {
// DOM focus is unreliable in TestSwarm
if ( QUnit.isSwarm && !focus ) {
assert.ok( true, "GAP: Could not observe focus change" );
}
done();
}, 50 );
}
);
QUnit.test( "focusin on document & window", function( assert ) {
assert.expect( 1 );
var counter = 0,
input = jQuery( "
" );
function increment() {
counter++;
}
input.appendTo( "#qunit-fixture" );
input[ 0 ].focus();
jQuery( window ).on( "focusout", increment );
jQuery( document ).on( "focusout", increment );
input[ 0 ].blur();
// DOM focus is unreliable in TestSwarm
if ( QUnit.isSwarm && counter === 0 ) {
assert.ok( true, "GAP: Could not observe focus change" );
}
assert.strictEqual( counter, 2,
"focusout handlers on document/window fired once only" );
jQuery( window ).off( "focusout", increment );
jQuery( document ).off( "focusout", increment );
} );
testIframe(
"jQuery.ready promise",
"event/promiseReady.html",
function( assert, jQuery, window, document, isOk ) {
assert.expect( 1 );
assert.ok( isOk, "$.when( $.ready ) works" );
},
jQuery.when ? QUnit.test : QUnit.skip
);
// need PHP here to make the incepted IFRAME hang
if ( hasPHP ) {
testIframe(
"jQuery.ready uses interactive",
"event/interactiveReady.html",
function( assert, jQuery, window, document, isOk ) {
assert.expect( 1 );
assert.ok( isOk, "jQuery fires ready when the DOM can truly be interacted with" );
}
);
}
testIframe(
"Focusing iframe element",
"event/focusElem.html",
function( assert, jQuery, window, document, isOk ) {
assert.expect( 1 );
assert.ok( isOk, "Focused an element in an iframe" );
}
);
testIframe(
"triggerHandler(onbeforeunload)",
"event/triggerunload.html",
function( assert, jQuery, window, document, isOk ) {
assert.expect( 1 );
assert.ok( isOk, "Triggered onbeforeunload without an error" );
}
);
// need PHP here to make the incepted IFRAME hang
if ( hasPHP ) {
testIframe(
"jQuery.ready synchronous load with long loading subresources",
"event/syncReady.html",
function( assert, jQuery, window, document, isOk ) {
assert.expect( 1 );
assert.ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
}
);
}
QUnit.test( "change handler should be detached from element", function( assert ) {
assert.expect( 2 );
var $fixture = jQuery( "
" ).appendTo( "body" ),
originRemoveEvent = jQuery.removeEvent,
wrapperRemoveEvent = function( elem, type, handle ) {
assert.equal( "change", type, "Event handler for 'change' event should be removed" );
assert.equal( "change-ie-leak", jQuery( elem ).attr( "id" ), "Event handler for 'change' event should be removed from appropriate element" );
originRemoveEvent( elem, type, handle );
};
jQuery.removeEvent = wrapperRemoveEvent;
$fixture.on( "change", function() {} );
$fixture.off( "change" );
$fixture.remove();
jQuery.removeEvent = originRemoveEvent;
} );
QUnit.test( "trigger click on checkbox, fires change event", function( assert ) {
assert.expect( 1 );
var check = jQuery( "#check2" );
var done = assert.async();
check.on( "change", function() {
// get it?
check.off( "change" );
assert.ok( true, "Change event fired as a result of triggered click" );
done();
} ).trigger( "click" );
} );
QUnit.test( "Namespace preserved when passed an Event (#12739)", function( assert ) {
assert.expect( 4 );
var markup = jQuery(
"
"
),
triggered = 0,
fooEvent;
markup.find( "div" )
.addBack()
.on( "foo.bar", function( e ) {
if ( !e.handled ) {
triggered++;
e.handled = true;
assert.equal( e.namespace, "bar", "namespace is bar" );
jQuery( e.target ).find( "div" ).each( function() {
jQuery( this ).triggerHandler( e );
} );
}
} )
.on( "foo.bar2", function() {
assert.ok( false, "foo.bar2 called on trigger " + triggered + " id " + this.id );
} );
markup.trigger( "foo.bar" );
markup.trigger( jQuery.Event( "foo.bar" ) );
fooEvent = jQuery.Event( "foo" );
fooEvent.namespace = "bar";
markup.trigger( fooEvent );
markup.remove();
assert.equal( triggered, 3, "foo.bar triggered" );
} );
QUnit.test( "make sure events cloned correctly", function( assert ) {
assert.expect( 18 );
var clone,
fixture = jQuery( "#qunit-fixture" ),
checkbox = jQuery( "#check1" ),
p = jQuery( "#firstp" );
fixture.on( "click change", function( event, result ) {
assert.ok( result, event.type + " on original element is fired" );
} ).on( "click", "#firstp", function( event, result ) {
assert.ok( result, "Click on original child element though delegation is fired" );
} ).on( "change", "#check1", function( event, result ) {
assert.ok( result, "Change on original child element though delegation is fired" );
} );
p.on( "click", function() {
assert.ok( true, "Click on original child element is fired" );
} );
checkbox.on( "change", function() {
assert.ok( true, "Change on original child element is fired" );
} );
fixture.clone().trigger( "click" ).trigger( "change" ); // 0 events should be fired
clone = fixture.clone( true );
clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
clone.remove();
clone = fixture.clone( true, true );
clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
fixture.off();
p.off();
checkbox.off();
p.trigger( "click" ); // 0 should be fired
checkbox.trigger( "change" ); // 0 should be fired
clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
clone.remove();
clone.find( "p" ).eq( 0 ).trigger( "click" ); // 0 should be fired
clone.find( "#check1" ).trigger( "change" ); // 0 events should fire
} );
QUnit.test( "String.prototype.namespace does not cause trigger() to throw (#13360)", function( assert ) {
assert.expect( 1 );
var errored = false;
String.prototype.namespace = function() {};
try {
jQuery( "
" ).trigger( "foo.bar" );
} catch ( e ) {
errored = true;
}
assert.equal( errored, false, "trigger() did not throw exception" );
delete String.prototype.namespace;
} );
QUnit.test( "Inline event result is returned (#13993)", function( assert ) {
assert.expect( 1 );
var result = jQuery( "
hello
" ).triggerHandler( "click" );
assert.equal( result, 42, "inline handler returned value" );
} );
QUnit.test( ".off() removes the expando when there's no more data", function( assert ) {
assert.expect( 2 );
var key,
div = jQuery( "
" ).appendTo( "#qunit-fixture" );
div.on( "click", false );
div.on( "custom", function() {
assert.ok( true, "Custom event triggered" );
} );
div.trigger( "custom" );
div.off( "click custom" );
// Make sure the expando is gone
for ( key in div[ 0 ] ) {
if ( /^jQuery/.test( key ) ) {
assert.strictEqual(
div[ 0 ][ key ], undefined,
"Expando was not removed when there was no more data"
);
}
}
} );
QUnit.test( "jQuery.Event( src ) does not require a target property", function( assert ) {
assert.expect( 2 );
var event = jQuery.Event( { type: "offtarget" } );
assert.equal( event.type, "offtarget", "correct type" );
assert.equal( event.target, undefined, "no target" );
} );
QUnit.test( "preventDefault() on focusin does not throw exception", function( assert ) {
assert.expect( 1 );
var done = assert.async(),
input = jQuery( "
" ).appendTo( "#form" );
input.on( "focusin", function( event ) {
if ( !done ) {
return;
}
var exceptionCaught;
try {
event.preventDefault();
} catch ( theException ) {
exceptionCaught = theException;
}
assert.strictEqual( exceptionCaught, undefined,
"Preventing default on focusin throws no exception" );
done();
done = null;
} );
input.trigger( "focus" );
// DOM focus is unreliable in TestSwarm; set a simulated event workaround timeout
setTimeout( function() {
if ( !done ) {
return;
}
input[ 0 ].addEventListener( "click", function( nativeEvent ) {
jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
} );
input[ 0 ].click();
}, QUnit.config.testTimeout / 4 || 1000 );
} );
QUnit.test( ".on('focus', fn) on a text node doesn't throw", function( assert ) {
assert.expect( 1 );
jQuery( document.createTextNode( "text" ) )
.on( "focus", function() {} );
assert.ok( true, "No crash" );
} );
QUnit.test( "Donor event interference", function( assert ) {
assert.expect( 8 );
var outer = jQuery(
"
" +
"" +
"
"
).appendTo( "#qunit-fixture" ),
input = jQuery( "#donor-input" );
input.on( "click", function( event ) {
assert.equal( event.type, "click", "click event at input" );
assert.ok( !event.isPropagationStopped(), "click event at input is still propagating" );
assert.equal( typeof event.originalEvent, "object",
"click event at input has originalEvent property" );
} );
outer.on( "click", function( event ) {
assert.equal( event.type, "click", "click event at ancestor" );
assert.ok( !event.isPropagationStopped(), "click event at ancestor is still propagating" );
assert.equal( typeof event.originalEvent, "object",
"click event at ancestor has originalEvent property" );
} );
input.on( "change", function( event ) {
assert.equal( event.type, "change", "change event at input" );
assert.equal( typeof event.originalEvent, "object",
"change event at input has originalEvent property" );
event.stopPropagation();
} );
input[ 0 ].click();
} );
QUnit.test(
"simulated events shouldn't forward stopPropagation/preventDefault methods",
function( assert ) {
assert.expect( 3 );
var outer = jQuery(
"
" +
"" +
"
"
).appendTo( "#qunit-fixture" ),
input = jQuery( "#donor-input" ),
spy = {};
jQuery( "#donor-form" )
.on( "simulated", function( event ) {
spy.prevent = sinon.stub( event.originalEvent, "preventDefault" );
event.preventDefault();
} )
.on( "simulated", function( event ) {
spy.stop = sinon.stub( event.originalEvent, "stopPropagation" );
event.stopPropagation();
} )
.on( "simulated", function( event ) {
spy.immediate = sinon.stub( event.originalEvent, "stopImmediatePropagation" );
event.stopImmediatePropagation();
} )
.on( "simulated", function( event ) {
assert.ok( false, "simulated event immediate propagation stopped" );
} );
outer
.on( "simulated", function( event ) {
assert.ok( false, "simulated event propagation stopped" );
} );
// Force a simulated event
input[ 0 ].addEventListener( "click", function( nativeEvent ) {
jQuery.event.simulate( "simulated", this, jQuery.event.fix( nativeEvent ) );
} );
input[ 0 ].click();
assert.strictEqual( spy.prevent.called, false, "Native preventDefault not called" );
assert.strictEqual( spy.stop.called, false, "Native stopPropagation not called" );
assert.strictEqual( spy.immediate.called, false,
"Native stopImmediatePropagation not called" );
}
);
QUnit.test( "originalEvent type of simulated event", function( assert ) {
assert.expect( 2 );
var outer = jQuery(
"
" +
"" +
"
"
).appendTo( "#qunit-fixture" ),
input = jQuery( "#donor-input" ),
done = assert.async(),
finish = function() {
// Remove jQuery handlers to ensure removal of capturing handlers on the document
outer.off( "focusin" );
done();
};
outer.on( "focusin", function( event ) {
assert.equal( event.type, "focusin", "focusin event at ancestor" );
assert.equal( event.originalEvent.type, "click",
"focus event at ancestor has correct originalEvent type" );
setTimeout( finish );
} );
input[ 0 ].addEventListener( "click", function( nativeEvent ) {
jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
} );
input[ 0 ].click();
} );
QUnit.test( "trigger('click') on radio passes extra params", function( assert ) {
assert.expect( 1 );
var $radio = jQuery( "
" ).appendTo( "#qunit-fixture" )
.on( "click", function( e, data ) {
assert.ok( data, "Trigger data is passed to radio click handler" );
} );
$radio.trigger( "click", [ true ] );
} );
// Support: IE <=9 only
// https://msdn.microsoft.com/en-us/library/hh801223(v=vs.85).aspx
QUnit.test( "VML with special event handlers (trac-7071)", function( assert ) {
assert.expect( 1 );
var ns = jQuery( "
" ).appendTo( "head" );
jQuery( "
" ).appendTo( "#form" );
jQuery( "#form" ).on( "keydown", function() {
assert.ok( true, "no error was thrown" );
} );
jQuery( "#oval" ).trigger( "click" ).trigger( "keydown" );
ns.remove();
} );
QUnit.test( "Check order of focusin/focusout events", function( assert ) {
assert.expect( 2 );
var focus, blur,
input = jQuery( "#name" );
input
.on( "focus", function() {
focus = true;
} )
.on( "focusin", function() {
assert.ok( !focus, "Focusin event should fire before focus does" );
focus = true;
} )
.on( "blur", function() {
blur = true;
} )
.on( "focusout", function() {
assert.ok( !blur, "Focusout event should fire before blur does" );
blur = true;
} );
// gain focus
input.trigger( "focus" );
// then lose it
jQuery( "#search" ).trigger( "focus" );
// cleanup
input.off();
// DOM focus is unreliable in TestSwarm
if ( !focus ) {
assert.ok( true, "GAP: Could not observe focus change" );
assert.ok( true, "GAP: Could not observe focus change" );
}
} );
QUnit.test( "focus-blur order (#12868)", function( assert ) {
assert.expect( 5 );
var order,
$text = jQuery( "#text1" ),
$radio = jQuery( "#radio1" ),
// Support: IE <=9 - 11+
// focus and blur events are asynchronous; this is the resulting mess.
// The browser window must be topmost for this to work properly!!
done = assert.async();
$radio[ 0 ].focus();
setTimeout( function() {
$text
.on( "focus", function() {
assert.equal( order++, 1, "text focus" );
} )
.on( "blur", function() {
assert.equal( order++, 0, "text blur" );
} );
$radio
.on( "focus", function() {
assert.equal( order++, 1, "radio focus" );
} )
.on( "blur", function() {
assert.equal( order++, 0, "radio blur" );
} );
// Enabled input getting focus
order = 0;
assert.equal( document.activeElement, $radio[ 0 ], "radio has focus" );
$text.trigger( "focus" );
setTimeout( function() {
// DOM focus is unreliable in TestSwarm
if ( order === 0 ) {
assert.ok( true, "GAP: Could not observe focus change" );
assert.ok( true, "GAP: Could not observe focus change" );
}
assert.equal( document.activeElement, $text[ 0 ], "text has focus" );
// Run handlers without native method on an input
order = 1;
$radio.triggerHandler( "focus" );
// Clean up
$text.off();
$radio.off();
done();
}, 50 );
}, 50 );
} );
QUnit.test( "Event handling works with multiple async focus events (gh-4350)", function( assert ) {
assert.expect( 3 );
var remaining = 3,
input = jQuery( "#name" ),
// Support: IE <=9 - 11+
// focus and blur events are asynchronous; this is the resulting mess.
// The browser window must be topmost for this to work properly!!
done = assert.async();
input
.on( "focus", function() {
remaining--;
assert.ok( true, "received focus event, expecting " + remaining + " more" );
if ( remaining > 0 ) {
input.trigger( "blur" );
} else {
done();
}
} )
.on( "blur", function() {
setTimeout( function() {
input.trigger( "focus" );
} );
} );
// gain focus
input.trigger( "focus" );
// DOM focus is unreliable in TestSwarm
setTimeout( function() {
if ( QUnit.isSwarm && remaining === 3 ) {
assert.ok( true, "GAP: Could not observe focus change" );
assert.ok( true, "GAP: Could not observe focus change" );
assert.ok( true, "GAP: Could not observe focus change" );
setTimeout( function() {
done();
} );
}
} );
} );
QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", function( assert ) {
assert.expect( 17 );
var parent = supportjQuery(
"
"
).appendTo( "#qunit-fixture" ),
targets = jQuery( parent[ 0 ].childNodes ),
checkbox = jQuery( targets[ 0 ] ),
data = [ "arg1", "arg2" ],
slice = data.slice,
// Support: IE <=9 - 11+
// focus and blur events are asynchronous; this is the resulting mess.
// The browser window must be topmost for this to work properly!!
done = assert.async();
// click (gh-4139)
assert.strictEqual( targets[ 0 ].checked, false, "checkbox unchecked before click" );
assert.strictEqual( targets[ 1 ].checked, false, "radio unchecked before click" );
targets.add( parent ).on( "click", function( event ) {
var type = event.target.type,
level = event.currentTarget === parent[ 0 ] ? "parent" : "";
assert.strictEqual( event.target.checked, true,
type + " toggled before invoking " + level + " handler" );
assert.deepEqual( slice.call( arguments, 1 ), data,
type + " " + level + " handler received correct data" );
} );
targets.trigger( "click", data );
assert.strictEqual( targets[ 0 ].checked, true,
"checkbox toggled after click (default action)" );
assert.strictEqual( targets[ 1 ].checked, true,
"radio toggled after event (default action)" );
// focus (gh-1741)
assert.notEqual( document.activeElement, checkbox[ 0 ],
"element not focused before focus event" );
checkbox.on( "focus blur", function( event ) {
var type = event.type;
assert.deepEqual( slice.call( arguments, 1 ), data,
type + " handler received correct data" );
} );
checkbox.trigger( "focus", data );
setTimeout( function() {
assert.strictEqual( document.activeElement, checkbox[ 0 ],
"element focused after focus event (default action)" );
checkbox.trigger( "blur", data );
setTimeout( function() {
assert.notEqual( document.activeElement, checkbox[ 0 ],
"element not focused after blur event (default action)" );
done();
}, 50 );
}, 50 );
} );
// TODO replace with an adaptation of
// https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
( function() {
supportjQuery.each(
{
checkbox: "
",
radio: "
"
},
makeTestFor3751
);
function makeTestFor3751( type, html ) {
var testName = "native-backed namespaced clicks are handled correctly (gh-3751) - " + type;
QUnit.test( testName, function( assert ) {
assert.expect( 2 );
var parent = supportjQuery( "
" + html + "
" ),
target = jQuery( parent[ 0 ].firstChild );
parent.appendTo( "#qunit-fixture" );
target.add( parent )
.on( "click.notFired", function( event ) {
assert.ok( false, "namespaced event should not be received" +
" by wrong-namespace listener at " + event.currentTarget.nodeName );
} )
.on( "click.fired", function( event ) {
assert.equal( event.target.checked, true,
"toggled before invoking handler at " + event.currentTarget.nodeName );
} )
.on( "click", function( event ) {
assert.ok( false, "namespaced event should not be received" +
" by non-namespaced listener at " + event.currentTarget.nodeName );
} );
target.trigger( "click.fired" );
} );
}
} )();