unit tests for using jQuery events on non-dom elements. fixes #3439. thanks morgan
[jquery.git] / test / unit / event.js
index e12f3b7..63c640d 100644 (file)
@@ -47,15 +47,11 @@ test("bind(), no data", function() {
 
 test("bind(), iframes", function() {
        // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
-       // var doc = document.getElementById("iframe").contentDocument;
-       // 
-       // doc.body.innerHTML = "<input type='text'/>";
-       //
-       // var input = doc.getElementsByTagName("input")[0];
-       //
-       // jQuery(input).bind("click",function() {
-       //      ok( true, "Binding to element inside iframe" );
-       // }).click();
+       var doc = jQuery("#loadediframe").contents();
+       
+       jQuery("div", doc).bind("click", function() {
+               ok( true, "Binding to element inside iframe" );
+       }).click().unbind('click');
 });
 
 test("bind(), trigger change on select", function() {
@@ -194,6 +190,11 @@ test("unbind(type)", function() {
        $elem.bind('error error2',error)
                 .unbind('error error2')
                 .trigger('error').triggerHandler('error2');
+       
+       message = "unbind without a type or handler";
+       $elem.bind("error error2.test",error)
+                .unbind()
+                .trigger("error").triggerHandler("error2");
 });
 
 test("unbind(eventObject)", function() {
@@ -417,6 +418,21 @@ test("trigger(eventObject, [data], [fn])", function() {
        $parent.unbind().remove();
 });
 
+test("jQuery.Event.currentTarget", function(){
+       expect(1);
+       
+       var counter = 0,
+               $elem = jQuery('<button>a</button>').click(function(e){
+               equals( e.currentTarget, this, "Check currentTarget on "+(counter++?"native":"fake") +" event" );
+       });
+       
+       // Fake event
+       $elem.trigger('click');
+       
+       // Cleanup
+       $elem.unbind();
+});
+
 test("toggle(Function, Function, ...)", function() {
        expect(11);
        
@@ -474,7 +490,7 @@ test("toggle(Function, Function, ...)", function() {
 });
 
 test(".live()/.die()", function() {
-       expect(36);
+       expect(54);
 
        var submit = 0, div = 0, livea = 0, liveb = 0;
 
@@ -533,10 +549,44 @@ test(".live()/.die()", function() {
        equals( livea, 5, "die Click on inner div" );
        equals( liveb, 2, "die Click on inner div" );
 
+       // Make sure that stopPropgation doesn't stop live events
+       jQuery("div#nothiddendivchild").live("click", function(e){ liveb++; e.stopPropagation(); });
+       jQuery("div#nothiddendivchild").trigger("click");
+       equals( submit, 1, "stopPropagation Click on inner div" );
+       equals( div, 6, "stopPropagation Click on inner div" );
+       equals( livea, 6, "stopPropagation Click on inner div" );
+       equals( liveb, 3, "stopPropagation Click on inner div" );
+
+       jQuery("div#nothiddendivchild").die("click");
        jQuery("div#nothiddendiv").die("click");
        jQuery("div").die("click");
        jQuery("div").die("submit");
 
+       // Test binding with a different context
+       var clicked = 0, container = jQuery('#main')[0];
+       jQuery("#foo", container).live("click", function(e){ clicked++; });
+       jQuery("div").trigger('click');
+       jQuery("#foo").trigger('click');
+       jQuery("#main").trigger('click');
+       jQuery("body").trigger('click');
+       equals( clicked, 2, "live with a context" );
+
+       // Make sure the event is actually stored on the context
+       ok( jQuery.data(container, "events").live, "live with a context" );
+
+       // Test unbinding with a different context
+       jQuery("#foo", container).die("click");
+       jQuery("#foo").trigger('click');
+       equals( clicked, 2, "die with a context");
+
+       // Test binding with event data
+       jQuery("#foo").live("click", true, function(e){ equals( e.data, true, "live with event data" ); });
+       jQuery("#foo").trigger("click").die("click");
+
+       // Test binding with trigger data
+       jQuery("#foo").live("click", function(e, data){ equals( data, true, "live with trigger data" ); });
+       jQuery("#foo").trigger("click", true).die("click");
+
        // Verify that return false prevents default action
        jQuery("#anchor2").live("click", function(){ return false; });
        var hash = window.location.hash;
@@ -588,6 +638,75 @@ test(".live()/.die()", function() {
 
        // Cleanup
        jQuery("#nothiddendiv").die("foo", callback);
+       
+       // Make sure we don't loose the target by DOM modifications
+       // after the bubble already reached the liveHandler
+       var livec = 0, elemDiv = jQuery("#nothiddendivchild").html('<span></span>').get(0);
+       
+       jQuery("#nothiddendivchild").live("click", function(e){ jQuery("#nothiddendivchild").html(''); });
+       jQuery("#nothiddendivchild").live("click", function(e){ if(e.target) {livec++;} });
+       
+       jQuery("#nothiddendiv span").click();
+       equals( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
+       equals( livec, 1, "Verify that second handler occurred even with nuked target." );
+       
+       // Cleanup
+       jQuery("#nothiddendivchild").die("click");
+
+       // Verify that .live() ocurs and cancel buble in the same order as
+       // we would expect .bind() and .click() without delegation
+       var lived = 0, livee = 0;
+       
+       // bind one pair in one order
+       jQuery('span#liveSpan1 a').live('click', function(){ lived++; return false; });
+       jQuery('span#liveSpan1').live('click', function(){ livee++; });
+
+       jQuery('span#liveSpan1 a').click();
+       equals( lived, 1, "Verify that only one first handler occurred." );
+       equals( livee, 0, "Verify that second handler don't." );
+
+       // and one pair in inverse
+       jQuery('#liveHandlerOrder span#liveSpan2').live('click', function(){ livee++; });
+       jQuery('#liveHandlerOrder span#liveSpan2 a').live('click', function(){ lived++; return false; });
+
+       jQuery('span#liveSpan2 a').click();
+       equals( lived, 2, "Verify that only one first handler occurred." );
+       equals( livee, 0, "Verify that second handler don't." );
+       
+       // Cleanup
+       jQuery("span#liveSpan1 a, span#liveSpan1, span#liveSpan2 a, span#liveSpan2").die("click");
+       
+       // Test this, target and currentTarget are correct
+       jQuery('span#liveSpan1').live('click', function(e){ 
+               equals( this.id, 'liveSpan1', 'Check the this within a live handler' );
+               equals( e.currentTarget.id, 'liveSpan1', 'Check the event.currentTarget within a live handler' );
+               equals( e.target.nodeName.toUpperCase(), 'A', 'Check the event.target within a live handler' );
+       });
+       
+       jQuery('span#liveSpan1 a').click();
+       
+       jQuery('span#liveSpan1').die('click');
+});
+
+test("Non DOM element events", function() {
+       expect(3);
+
+       jQuery({})
+               .bind('nonelementglobal', function(e) {
+                       ok( true, "Global event on non-DOM annonymos object triggered" );
+               });
+
+       var o = {};
+
+       jQuery(o)
+               .bind('nonelementobj', function(e) {
+                       ok( true, "Event on non-DOM object triggered" );
+               }).bind('nonelementglobal', function() {
+                       ok( true, "Global event on non-DOM object triggered" );
+               });
+
+       jQuery(o).trigger('nonelementobj');
+       jQuery.event.trigger('nonelementglobal');
 });
 
 /*