Honor stopImmediatePropagation for live/delegate event handlers. Fixes #7217.
[jquery.git] / test / unit / event.js
1 module("event");
2
3 test("null or undefined handler", function() {
4         expect(2);
5   // Supports Fixes bug #7229
6   try {
7   
8     jQuery("#firstp").click(null);
9   
10     ok(true, "Passing a null handler will not throw an exception");
11
12   } catch (e) {}  
13
14   try {
15   
16     jQuery("#firstp").click(undefined);
17   
18     ok(true, "Passing an undefined handler will not throw an exception");
19
20   } catch (e) {}  
21 });
22
23 test("bind(), with data", function() {
24         expect(3);
25         var handler = function(event) {
26                 ok( event.data, "bind() with data, check passed data exists" );
27                 equals( event.data.foo, "bar", "bind() with data, Check value of passed data" );
28         };
29         jQuery("#firstp").bind("click", {foo: "bar"}, handler).click().unbind("click", handler);
30
31         ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
32 });
33
34 test("click(), with data", function() {
35         expect(3);
36         var handler = function(event) {
37                 ok( event.data, "bind() with data, check passed data exists" );
38                 equals( event.data.foo, "bar", "bind() with data, Check value of passed data" );
39         };
40         jQuery("#firstp").click({foo: "bar"}, handler).click().unbind("click", handler);
41
42         ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
43 });
44
45 test("bind(), with data, trigger with data", function() {
46         expect(4);
47         var handler = function(event, data) {
48                 ok( event.data, "check passed data exists" );
49                 equals( event.data.foo, "bar", "Check value of passed data" );
50                 ok( data, "Check trigger data" );
51                 equals( data.bar, "foo", "Check value of trigger data" );
52         };
53         jQuery("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]).unbind("click", handler);
54 });
55
56 test("bind(), multiple events at once", function() {
57         expect(2);
58         var clickCounter = 0,
59                 mouseoverCounter = 0;
60         var handler = function(event) {
61                 if (event.type == "click")
62                         clickCounter += 1;
63                 else if (event.type == "mouseover")
64                         mouseoverCounter += 1;
65         };
66         jQuery("#firstp").bind("click mouseover", handler).trigger("click").trigger("mouseover");
67         equals( clickCounter, 1, "bind() with multiple events at once" );
68         equals( mouseoverCounter, 1, "bind() with multiple events at once" );
69 });
70
71 test("bind(), multiple events at once and namespaces", function() {
72         expect(7);
73
74         var cur, obj = {};
75
76         var div = jQuery("<div/>").bind("focusin.a", function(e) {
77                 equals( e.type, cur, "Verify right single event was fired." );
78         });
79
80         cur = "focusin";
81         div.trigger("focusin.a");
82
83         div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
84                 equals( e.type, cur, "Verify right multi event was fired." );
85                 equals( e.data, obj, "Make sure the data came in correctly." );
86         });
87
88         cur = "click";
89         div.trigger("click");
90
91         cur = "mouseover";
92         div.trigger("mouseover");
93
94         div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
95                 equals( e.type, cur, "Verify right multi event was fired." );
96         });
97
98         cur = "focusin";
99         div.trigger("focusin.a");
100
101         cur = "focusout";
102         div.trigger("focusout.b");
103 });
104
105 test("bind(), namespace with special add", function() {
106         expect(24);
107
108         var div = jQuery("<div/>").bind("test", function(e) {
109                 ok( true, "Test event fired." );
110         });
111
112         var i = 0;
113
114         jQuery.event.special.test = {
115                 _default: function(e) {
116                         equals( this, document, "Make sure we're at the top of the chain." );
117                         equals( e.type, "test", "And that we're still dealing with a test event." );
118                         equals( e.target, div[0], "And that the target is correct." );
119                 },
120                 setup: function(){},
121                 teardown: function(){
122                         ok(true, "Teardown called.");
123                 },
124                 add: function( handleObj ) {
125                         var handler = handleObj.handler;
126                         handleObj.handler = function(e) {
127                                 e.xyz = ++i;
128                                 handler.apply( this, arguments );
129                         };
130                 },
131                 remove: function() {
132                         ok(true, "Remove called.");
133                 }
134         };
135
136         div.bind("test.a", {x: 1}, function(e) {
137                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
138                 equals( e.data.x, 1, "Make sure data is attached properly." );
139         });
140
141         div.bind("test.b", {x: 2}, function(e) {
142                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
143                 equals( e.data.x, 2, "Make sure data is attached properly." );
144         });
145
146         // Should trigger 5
147         div.trigger("test");
148
149         // Should trigger 2
150         div.trigger("test.a");
151
152         // Should trigger 2
153         div.trigger("test.b");
154
155         // Should trigger 4
156         div.unbind("test");
157
158         div = jQuery("<div/>").bind("test", function(e) {
159                 ok( true, "Test event fired." );
160         });
161
162         // Should trigger 2
163         div.appendTo("#main").remove();
164
165         delete jQuery.event.special.test;
166 });
167
168 test("bind(), no data", function() {
169         expect(1);
170         var handler = function(event) {
171                 ok ( !event.data, "Check that no data is added to the event object" );
172         };
173         jQuery("#firstp").bind("click", handler).trigger("click");
174 });
175
176 test("bind/one/unbind(Object)", function(){
177         expect(6);
178         
179         var clickCounter = 0, mouseoverCounter = 0;
180         function handler(event) {
181                 if (event.type == "click")
182                         clickCounter++;
183                 else if (event.type == "mouseover")
184                         mouseoverCounter++;
185         };
186         
187         function handlerWithData(event) {
188                 if (event.type == "click")
189                         clickCounter += event.data;
190                 else if (event.type == "mouseover")
191                         mouseoverCounter += event.data;
192         };
193         
194         function trigger(){
195                 $elem.trigger("click").trigger("mouseover");
196         }
197         
198         var $elem = jQuery("#firstp")
199                 // Regular bind
200                 .bind({
201                         click:handler,
202                         mouseover:handler
203                 })
204                 // Bind with data
205                 .one({
206                         click:handlerWithData,
207                         mouseover:handlerWithData
208                 }, 2 );
209         
210         trigger();
211         
212         equals( clickCounter, 3, "bind(Object)" );
213         equals( mouseoverCounter, 3, "bind(Object)" );
214         
215         trigger();
216         equals( clickCounter, 4, "bind(Object)" );
217         equals( mouseoverCounter, 4, "bind(Object)" );
218         
219         jQuery("#firstp").unbind({
220                 click:handler,
221                 mouseover:handler
222         });
223
224         trigger();
225         equals( clickCounter, 4, "bind(Object)" );
226         equals( mouseoverCounter, 4, "bind(Object)" );
227 });
228
229 test("live/die(Object), delegate/undelegate(String, Object)", function() {
230         expect(6);
231         
232         var clickCounter = 0, mouseoverCounter = 0,
233                 $p = jQuery("#firstp"), $a = $p.find("a:first");
234         
235         var events = {
236                 click: function( event ) {
237                         clickCounter += ( event.data || 1 );
238                 },
239                 mouseover: function( event ) {
240                         mouseoverCounter += ( event.data || 1 );
241                 }
242         };
243         
244         function trigger() {
245                 $a.trigger("click").trigger("mouseover");
246         }
247         
248         $a.live( events );
249         $p.delegate( "a", events, 2 );
250         
251         trigger();
252         equals( clickCounter, 3, "live/delegate" );
253         equals( mouseoverCounter, 3, "live/delegate" );
254         
255         $p.undelegate( "a", events );
256         
257         trigger();
258         equals( clickCounter, 4, "undelegate" );
259         equals( mouseoverCounter, 4, "undelegate" );
260         
261         $a.die( events );
262         
263         trigger();
264         equals( clickCounter, 4, "die" );
265         equals( mouseoverCounter, 4, "die" );
266 });
267
268 test("live/delegate immediate propagation", function() {
269         expect(2);
270         
271         var $p = jQuery("#firstp"), $a = $p.find("a:first"), lastClick;
272         
273         lastClick = "";
274         $a.live( "click", function(e) { 
275                 lastClick = "click1"; 
276                 e.stopImmediatePropagation();
277         });
278         $a.live( "click", function(e) {
279                 lastClick = "click2";
280         });
281         $a.trigger( "click" );
282         equals( lastClick, "click1", "live stopImmediatePropagation" );
283         $a.die( "click" );
284         
285         lastClick = "";
286         $p.delegate( "a", "click", function(e) { 
287                 lastClick = "click1"; 
288                 e.stopImmediatePropagation();
289         });
290         $p.delegate( "a", "click", function(e) {
291                 lastClick = "click2";
292         });
293         $a.trigger( "click" );
294         equals( lastClick, "click1", "delegate stopImmediatePropagation" );
295         $p.undelegate( "click" );
296 });
297
298 test("bind(), iframes", function() {
299         // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
300         var doc = jQuery("#loadediframe").contents();
301         
302         jQuery("div", doc).bind("click", function() {
303                 ok( true, "Binding to element inside iframe" );
304         }).click().unbind('click');
305 });
306
307 test("bind(), trigger change on select", function() {
308         expect(5);
309         var counter = 0;
310         function selectOnChange(event) {
311                 equals( event.data, counter++, "Event.data is not a global event object" );
312         };
313         jQuery("#form select").each(function(i){
314                 jQuery(this).bind('change', i, selectOnChange);
315         }).trigger('change');
316 });
317
318 test("bind(), namespaced events, cloned events", function() {
319         expect(6);
320
321         jQuery("#firstp").bind("custom.test",function(e){
322                 ok(true, "Custom event triggered");
323         });
324
325         jQuery("#firstp").bind("click",function(e){
326                 ok(true, "Normal click triggered");
327         });
328
329         jQuery("#firstp").bind("click.test",function(e){
330                 ok(true, "Namespaced click triggered");
331         });
332
333         // Trigger both bound fn (2)
334         jQuery("#firstp").trigger("click");
335
336         // Trigger one bound fn (1)
337         jQuery("#firstp").trigger("click.test");
338
339         // Remove only the one fn
340         jQuery("#firstp").unbind("click.test");
341
342         // Trigger the remaining fn (1)
343         jQuery("#firstp").trigger("click");
344
345         // Remove the remaining fn
346         jQuery("#firstp").unbind(".test");
347
348         // Trigger the remaining fn (0)
349         jQuery("#firstp").trigger("custom");
350
351         // using contents will get comments regular, text, and comment nodes
352         jQuery("#nonnodes").contents().bind("tester", function () {
353                 equals(this.nodeType, 1, "Check node,textnode,comment bind just does real nodes" );
354         }).trigger("tester");
355
356         // Make sure events stick with appendTo'd elements (which are cloned) #2027
357         jQuery("<a href='#fail' class='test'>test</a>").click(function(){ return false; }).appendTo("p");
358         ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
359 });
360
361 test("bind(), multi-namespaced events", function() {
362         expect(6);
363         
364         var order = [
365                 "click.test.abc",
366                 "click.test.abc",
367                 "click.test",
368                 "click.test.abc",
369                 "click.test",
370                 "custom.test2"
371         ];
372         
373         function check(name, msg){
374                 same(name, order.shift(), msg);
375         }
376
377         jQuery("#firstp").bind("custom.test",function(e){
378                 check("custom.test", "Custom event triggered");
379         });
380
381         jQuery("#firstp").bind("custom.test2",function(e){
382                 check("custom.test2", "Custom event triggered");
383         });
384
385         jQuery("#firstp").bind("click.test",function(e){
386                 check("click.test", "Normal click triggered");
387         });
388
389         jQuery("#firstp").bind("click.test.abc",function(e){
390                 check("click.test.abc", "Namespaced click triggered");
391         });
392         
393         // Those would not trigger/unbind (#5303)
394         jQuery("#firstp").trigger("click.a.test");
395         jQuery("#firstp").unbind("click.a.test");
396
397         // Trigger both bound fn (1)
398         jQuery("#firstp").trigger("click.test.abc");
399
400         // Trigger one bound fn (1)
401         jQuery("#firstp").trigger("click.abc");
402
403         // Trigger two bound fn (2)
404         jQuery("#firstp").trigger("click.test");
405
406         // Remove only the one fn
407         jQuery("#firstp").unbind("click.abc");
408
409         // Trigger the remaining fn (1)
410         jQuery("#firstp").trigger("click");
411
412         // Remove the remaining fn
413         jQuery("#firstp").unbind(".test");
414
415         // Trigger the remaining fn (1)
416         jQuery("#firstp").trigger("custom");
417 });
418
419 test("bind(), with same function", function() {
420         expect(2)
421
422         var count = 0 ,  func = function(){
423                 count++;
424         };
425
426         jQuery("#liveHandlerOrder").bind("foo.bar", func).bind("foo.zar", func);
427         jQuery("#liveHandlerOrder").trigger("foo.bar");
428
429         equals(count, 1, "Verify binding function with multiple namespaces." );
430
431         jQuery("#liveHandlerOrder").unbind("foo.bar", func).unbind("foo.zar", func);
432         jQuery("#liveHandlerOrder").trigger("foo.bar");
433
434         equals(count, 1, "Verify that removing events still work." );
435 });
436
437 test("bind(), make sure order is maintained", function() {
438         expect(1);
439
440         var elem = jQuery("#firstp"), log = [], check = [];
441
442         for ( var i = 0; i < 100; i++ ) (function(i){
443                 elem.bind( "click", function(){
444                         log.push( i );
445                 });
446
447                 check.push( i );
448         })(i);
449
450         elem.trigger("click");
451
452         equals( log.join(","), check.join(","), "Make sure order was maintained." );
453
454         elem.unbind("click");
455 });
456  
457 test("bind(), with different this object", function() {
458         expect(4);
459         var thisObject = { myThis: true },
460                 data = { myData: true },
461                 handler1 = function( event ) {
462                         equals( this, thisObject, "bind() with different this object" );
463                 },
464                 handler2 = function( event ) {
465                         equals( this, thisObject, "bind() with different this object and data" );
466                         equals( event.data, data, "bind() with different this object and data" );
467                 };
468         
469         jQuery("#firstp")
470                 .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
471                 .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2);
472
473         ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
474 });
475
476 test("bind(name, false), unbind(name, false)", function() {
477         expect(3);
478
479         var main = 0;
480         jQuery("#main").bind("click", function(e){ main++; });
481         jQuery("#ap").trigger("click");
482         equals( main, 1, "Verify that the trigger happened correctly." );
483
484         main = 0;
485         jQuery("#ap").bind("click", false);
486         jQuery("#ap").trigger("click");
487         equals( main, 0, "Verify that no bubble happened." );
488
489         main = 0;
490         jQuery("#ap").unbind("click", false);
491         jQuery("#ap").trigger("click");
492         equals( main, 1, "Verify that the trigger happened correctly." );
493 });
494
495 test("bind()/trigger()/unbind() on plain object", function() {
496         expect( 7 );
497
498         var obj = {};
499
500         // Make sure it doesn't complain when no events are found
501         jQuery(obj).trigger("test");
502
503         // Make sure it doesn't complain when no events are found
504         jQuery(obj).unbind("test");
505
506         jQuery(obj).bind("test", function(){
507                 ok( true, "Custom event run." );
508         });
509
510         var events = jQuery(obj).data("__events__");
511         ok( events, "Object has events bound." );
512         equals( obj.events, undefined, "Events object on plain objects is not events" );
513         equals( typeof events, "function", "'events' expando is a function on plain objects." );
514         equals( obj.test, undefined, "Make sure that test event is not on the plain object." );
515         equals( obj.handle, undefined, "Make sure that the event handler is not on the plain object." );
516
517         // Should trigger 1
518         jQuery(obj).trigger("test");
519
520         jQuery(obj).unbind("test");
521
522         // Should trigger 0
523         jQuery(obj).trigger("test");
524
525         // Make sure it doesn't complain when no events are found
526         jQuery(obj).unbind("test");
527         
528         equals( obj.__events__, undefined, "Make sure events object is removed" );
529 });
530
531 test("unbind(type)", function() {
532         expect( 0 );
533         
534         var $elem = jQuery("#firstp"),
535                 message;
536
537         function error(){
538                 ok( false, message );
539         }
540         
541         message = "unbind passing function";
542         $elem.bind('error1', error).unbind('error1',error).triggerHandler('error1');
543         
544         message = "unbind all from event";
545         $elem.bind('error1', error).unbind('error1').triggerHandler('error1');
546         
547         message = "unbind all";
548         $elem.bind('error1', error).unbind().triggerHandler('error1');
549         
550         message = "unbind many with function";
551         $elem.bind('error1 error2',error)
552                  .unbind('error1 error2', error )
553                  .trigger('error1').triggerHandler('error2');
554
555         message = "unbind many"; // #3538
556         $elem.bind('error1 error2',error)
557                  .unbind('error1 error2')
558                  .trigger('error1').triggerHandler('error2');
559         
560         message = "unbind without a type or handler";
561         $elem.bind("error1 error2.test",error)
562                  .unbind()
563                  .trigger("error1").triggerHandler("error2");
564 });
565
566 test("unbind(eventObject)", function() {
567         expect(4);
568         
569         var $elem = jQuery("#firstp"),
570                 num;
571
572         function assert( expected ){
573                 num = 0;
574                 $elem.trigger('foo').triggerHandler('bar');
575                 equals( num, expected, "Check the right handlers are triggered" );
576         }
577         
578         $elem
579                 // This handler shouldn't be unbound
580                 .bind('foo', function(){
581                         num += 1;
582                 })
583                 .bind('foo', function(e){
584                         $elem.unbind( e )
585                         num += 2;
586                 })
587                 // Neither this one
588                 .bind('bar', function(){
589                         num += 4;
590                 });
591                 
592         assert( 7 );
593         assert( 5 );
594         
595         $elem.unbind('bar');
596         assert( 1 );
597         
598         $elem.unbind(); 
599         assert( 0 );
600 });
601
602 test("hover()", function() {
603         var times = 0,
604                 handler1 = function( event ) { ++times; },
605                 handler2 = function( event ) { ++times; };
606
607         jQuery("#firstp")
608                 .hover(handler1, handler2)
609                 .mouseenter().mouseleave()
610                 .unbind("mouseenter", handler1)
611                 .unbind("mouseleave", handler2)
612                 .hover(handler1)
613                 .mouseenter().mouseleave()
614                 .unbind("mouseenter mouseleave", handler1)
615                 .mouseenter().mouseleave();
616
617         equals( times, 4, "hover handlers fired" );
618 });
619
620 test("trigger() shortcuts", function() {
621         expect(6);
622         jQuery('<li><a href="#">Change location</a></li>').prependTo('#firstUL').find('a').bind('click', function() {
623                 var close = jQuery('spanx', this); // same with jQuery(this).find('span');
624                 equals( close.length, 0, "Context element does not exist, length must be zero" );
625                 ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
626                 return false;
627         }).click();
628         
629         jQuery("#check1").click(function() {
630                 ok( true, "click event handler for checkbox gets fired twice, see #815" );
631         }).click();
632         
633         var counter = 0;
634         jQuery('#firstp')[0].onclick = function(event) {
635                 counter++;
636         };
637         jQuery('#firstp').click();
638         equals( counter, 1, "Check that click, triggers onclick event handler also" );
639         
640         var clickCounter = 0;
641         jQuery('#simon1')[0].onclick = function(event) {
642                 clickCounter++;
643         };
644         jQuery('#simon1').click();
645         equals( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
646         
647         jQuery('<img />').load(function(){
648                 ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
649         }).load();
650 });
651
652 test("trigger() bubbling", function() {
653         expect(14);
654
655         var doc = 0, html = 0, body = 0, main = 0, ap = 0;
656
657         jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } });
658         jQuery("html").bind("click", function(e){ html++; });
659         jQuery("body").bind("click", function(e){ body++; });
660         jQuery("#main").bind("click", function(e){ main++; });
661         jQuery("#ap").bind("click", function(){ ap++; return false; });
662
663         jQuery("html").trigger("click");
664         equals( doc, 1, "HTML bubble" );
665         equals( html, 1, "HTML bubble" );
666
667         jQuery("body").trigger("click");
668         equals( doc, 2, "Body bubble" );
669         equals( html, 2, "Body bubble" );
670         equals( body, 1, "Body bubble" );
671
672         jQuery("#main").trigger("click");
673         equals( doc, 3, "Main bubble" );
674         equals( html, 3, "Main bubble" );
675         equals( body, 2, "Main bubble" );
676         equals( main, 1, "Main bubble" );
677
678         jQuery("#ap").trigger("click");
679         equals( doc, 3, "ap bubble" );
680         equals( html, 3, "ap bubble" );
681         equals( body, 2, "ap bubble" );
682         equals( main, 1, "ap bubble" );
683         equals( ap, 1, "ap bubble" );
684 });
685
686 test("trigger(type, [data], [fn])", function() {
687         expect(14);
688
689         var handler = function(event, a, b, c) {
690                 equals( event.type, "click", "check passed data" );
691                 equals( a, 1, "check passed data" );
692                 equals( b, "2", "check passed data" );
693                 equals( c, "abc", "check passed data" );
694                 return "test";
695         };
696
697         var $elem = jQuery("#firstp");
698
699         // Simulate a "native" click
700         $elem[0].click = function(){
701                 ok( true, "Native call was triggered" );
702         };
703
704         // Triggers handlrs and native
705         // Trigger 5
706         $elem.bind("click", handler).trigger("click", [1, "2", "abc"]);
707
708         // Simulate a "native" click
709         $elem[0].click = function(){
710                 ok( false, "Native call was triggered" );
711         };
712
713         // Trigger only the handlers (no native)
714         // Triggers 5
715         equals( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
716
717         var pass = true;
718         try {
719                 jQuery('#form input:first').hide().trigger('focus');
720         } catch(e) {
721                 pass = false;
722         }
723         ok( pass, "Trigger focus on hidden element" );
724         
725         pass = true;
726         try {
727                 jQuery('table:first').bind('test:test', function(){}).trigger('test:test');
728         } catch (e) {
729                 pass = false;
730         }
731         ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
732
733         var form = jQuery("<form action=''></form>").appendTo("body");
734
735         // Make sure it can be prevented locally
736         form.submit(function(){
737                 ok( true, "Local bind still works." );
738                 return false;
739         });
740
741         // Trigger 1
742         form.trigger("submit");
743
744         form.unbind("submit");
745
746         jQuery(document).submit(function(){
747                 ok( true, "Make sure bubble works up to document." );
748                 return false;
749         });
750
751         // Trigger 1
752         form.trigger("submit");
753
754         jQuery(document).unbind("submit");
755
756         form.remove();
757 });
758
759 test("jQuery.Event.currentTarget", function(){
760 });
761
762 test("trigger(eventObject, [data], [fn])", function() {
763         expect(25);
764         
765         var $parent = jQuery('<div id="par" />').hide().appendTo('body'),
766                 $child = jQuery('<p id="child">foo</p>').appendTo( $parent );
767         
768         var event = jQuery.Event("noNew");      
769         ok( event != window, "Instantiate jQuery.Event without the 'new' keyword" );
770         equals( event.type, "noNew", "Verify its type" );
771         
772         equals( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
773         equals( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
774         equals( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
775         
776         event.preventDefault();
777         equals( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
778         event.stopPropagation();
779         equals( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
780         
781         event.isPropagationStopped = function(){ return false };
782         event.stopImmediatePropagation();
783         equals( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
784         equals( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
785         
786         $parent.bind('foo',function(e){
787                 // Tries bubbling
788                 equals( e.type, 'foo', 'Verify event type when passed passing an event object' );
789                 equals( e.target.id, 'child', 'Verify event.target when passed passing an event object' );
790                 equals( e.currentTarget.id, 'par', 'Verify event.target when passed passing an event object' );
791                 equals( e.secret, 'boo!', 'Verify event object\'s custom attribute when passed passing an event object' );
792         });
793         
794         // test with an event object
795         event = new jQuery.Event("foo");
796         event.secret = 'boo!';
797         $child.trigger(event);
798         
799         // test with a literal object
800         $child.trigger({type:'foo', secret:'boo!'});
801         
802         $parent.unbind();
803
804         function error(){
805                 ok( false, "This assertion shouldn't be reached");
806         }
807         
808         $parent.bind('foo', error );
809         
810         $child.bind('foo',function(e, a, b, c ){
811                 equals( arguments.length, 4, "Check arguments length");
812                 equals( a, 1, "Check first custom argument");
813                 equals( b, 2, "Check second custom argument");
814                 equals( c, 3, "Check third custom argument");
815                 
816                 equals( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
817                 equals( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
818                 equals( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
819                 
820                 // Skips both errors
821                 e.stopImmediatePropagation();
822                 
823                 return "result";
824         });
825         
826         // We should add this back in when we want to test the order
827         // in which event handlers are iterated.
828         //$child.bind('foo', error );
829         
830         event = new jQuery.Event("foo");
831         $child.trigger( event, [1,2,3] ).unbind();
832         equals( event.result, "result", "Check event.result attribute");
833         
834         // Will error if it bubbles
835         $child.triggerHandler('foo');
836         
837         $child.unbind();
838         $parent.unbind().remove();
839 });
840
841 test("jQuery.Event.currentTarget", function(){
842         expect(1);
843         
844         var counter = 0,
845                 $elem = jQuery('<button>a</button>').click(function(e){
846                 equals( e.currentTarget, this, "Check currentTarget on "+(counter++?"native":"fake") +" event" );
847         });
848         
849         // Fake event
850         $elem.trigger('click');
851         
852         // Cleanup
853         $elem.unbind();
854 });
855
856 test("toggle(Function, Function, ...)", function() {
857         expect(16);
858         
859         var count = 0,
860                 fn1 = function(e) { count++; },
861                 fn2 = function(e) { count--; },
862                 preventDefault = function(e) { e.preventDefault() },
863                 link = jQuery('#mark');
864         link.click(preventDefault).click().toggle(fn1, fn2).click().click().click().click().click();
865         equals( count, 1, "Check for toggle(fn, fn)" );
866
867         jQuery("#firstp").toggle(function () {
868                 equals(arguments.length, 4, "toggle correctly passes through additional triggered arguments, see #1701" )
869         }, function() {}).trigger("click", [ 1, 2, 3 ]);
870
871         var first = 0;
872         jQuery("#simon1").one("click", function() {
873                 ok( true, "Execute event only once" );
874                 jQuery(this).toggle(function() {
875                         equals( first++, 0, "toggle(Function,Function) assigned from within one('xxx'), see #1054" );
876                 }, function() {
877                         equals( first, 1, "toggle(Function,Function) assigned from within one('xxx'), see #1054" );
878                 });
879                 return false;
880         }).click().click().click();
881         
882         var turn = 0;
883         var fns = [
884                 function(){
885                         turn = 1;
886                 },
887                 function(){
888                         turn = 2;
889                 },
890                 function(){
891                         turn = 3;
892                 }
893         ];
894         
895         var $div = jQuery("<div>&nbsp;</div>").toggle( fns[0], fns[1], fns[2] );
896         $div.click();
897         equals( turn, 1, "Trying toggle with 3 functions, attempt 1 yields 1");
898         $div.click();
899         equals( turn, 2, "Trying toggle with 3 functions, attempt 2 yields 2");
900         $div.click();
901         equals( turn, 3, "Trying toggle with 3 functions, attempt 3 yields 3");
902         $div.click();
903         equals( turn, 1, "Trying toggle with 3 functions, attempt 4 yields 1");
904         $div.click();
905         equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2");
906         
907         $div.unbind('click',fns[0]);
908         var data = jQuery.data( $div[0], 'events' );
909         ok( !data, "Unbinding one function from toggle unbinds them all");
910
911         // Test Multi-Toggles
912         var a = [], b = [];
913         $div = jQuery("<div/>");
914         $div.toggle(function(){ a.push(1); }, function(){ a.push(2); });
915         $div.click();
916         same( a, [1], "Check that a click worked." );
917
918         $div.toggle(function(){ b.push(1); }, function(){ b.push(2); });
919         $div.click();
920         same( a, [1,2], "Check that a click worked with a second toggle." );
921         same( b, [1], "Check that a click worked with a second toggle." );
922
923         $div.click();
924         same( a, [1,2,1], "Check that a click worked with a second toggle, second click." );
925         same( b, [1,2], "Check that a click worked with a second toggle, second click." );
926 });
927
928 test(".live()/.die()", function() {
929         expect(66);
930
931         var submit = 0, div = 0, livea = 0, liveb = 0;
932
933         jQuery("div").live("submit", function(){ submit++; return false; });
934         jQuery("div").live("click", function(){ div++; });
935         jQuery("div#nothiddendiv").live("click", function(){ livea++; });
936         jQuery("div#nothiddendivchild").live("click", function(){ liveb++; });
937
938         // Nothing should trigger on the body
939         jQuery("body").trigger("click");
940         equals( submit, 0, "Click on body" );
941         equals( div, 0, "Click on body" );
942         equals( livea, 0, "Click on body" );
943         equals( liveb, 0, "Click on body" );
944
945         // This should trigger two events
946         submit = 0, div = 0, livea = 0, liveb = 0;
947         jQuery("div#nothiddendiv").trigger("click");
948         equals( submit, 0, "Click on div" );
949         equals( div, 1, "Click on div" );
950         equals( livea, 1, "Click on div" );
951         equals( liveb, 0, "Click on div" );
952
953         // This should trigger three events (w/ bubbling)
954         submit = 0, div = 0, livea = 0, liveb = 0;
955         jQuery("div#nothiddendivchild").trigger("click");
956         equals( submit, 0, "Click on inner div" );
957         equals( div, 2, "Click on inner div" );
958         equals( livea, 1, "Click on inner div" );
959         equals( liveb, 1, "Click on inner div" );
960
961         // This should trigger one submit
962         submit = 0, div = 0, livea = 0, liveb = 0;
963         jQuery("div#nothiddendivchild").trigger("submit");
964         equals( submit, 1, "Submit on div" );
965         equals( div, 0, "Submit on div" );
966         equals( livea, 0, "Submit on div" );
967         equals( liveb, 0, "Submit on div" );
968
969         // Make sure no other events were removed in the process
970         submit = 0, div = 0, livea = 0, liveb = 0;
971         jQuery("div#nothiddendivchild").trigger("click");
972         equals( submit, 0, "die Click on inner div" );
973         equals( div, 2, "die Click on inner div" );
974         equals( livea, 1, "die Click on inner div" );
975         equals( liveb, 1, "die Click on inner div" );
976
977         // Now make sure that the removal works
978         submit = 0, div = 0, livea = 0, liveb = 0;
979         jQuery("div#nothiddendivchild").die("click");
980         jQuery("div#nothiddendivchild").trigger("click");
981         equals( submit, 0, "die Click on inner div" );
982         equals( div, 2, "die Click on inner div" );
983         equals( livea, 1, "die Click on inner div" );
984         equals( liveb, 0, "die Click on inner div" );
985
986         // Make sure that the click wasn't removed too early
987         submit = 0, div = 0, livea = 0, liveb = 0;
988         jQuery("div#nothiddendiv").trigger("click");
989         equals( submit, 0, "die Click on inner div" );
990         equals( div, 1, "die Click on inner div" );
991         equals( livea, 1, "die Click on inner div" );
992         equals( liveb, 0, "die Click on inner div" );
993
994         // Make sure that stopPropgation doesn't stop live events
995         submit = 0, div = 0, livea = 0, liveb = 0;
996         jQuery("div#nothiddendivchild").live("click", function(e){ liveb++; e.stopPropagation(); });
997         jQuery("div#nothiddendivchild").trigger("click");
998         equals( submit, 0, "stopPropagation Click on inner div" );
999         equals( div, 1, "stopPropagation Click on inner div" );
1000         equals( livea, 0, "stopPropagation Click on inner div" );
1001         equals( liveb, 1, "stopPropagation Click on inner div" );
1002
1003         // Make sure click events only fire with primary click
1004         submit = 0, div = 0, livea = 0, liveb = 0;
1005         var event = jQuery.Event("click");
1006         event.button = 1;
1007         jQuery("div#nothiddendiv").trigger(event);
1008
1009         equals( livea, 0, "live secondary click" );
1010
1011         jQuery("div#nothiddendivchild").die("click");
1012         jQuery("div#nothiddendiv").die("click");
1013         jQuery("div").die("click");
1014         jQuery("div").die("submit");
1015
1016         // Test binding with a different context
1017         var clicked = 0, container = jQuery('#main')[0];
1018         jQuery("#foo", container).live("click", function(e){ clicked++; });
1019         jQuery("div").trigger('click');
1020         jQuery("#foo").trigger('click');
1021         jQuery("#main").trigger('click');
1022         jQuery("body").trigger('click');
1023         equals( clicked, 2, "live with a context" );
1024
1025         // Make sure the event is actually stored on the context
1026         ok( jQuery.data(container, "events").live, "live with a context" );
1027
1028         // Test unbinding with a different context
1029         jQuery("#foo", container).die("click");
1030         jQuery("#foo").trigger('click');
1031         equals( clicked, 2, "die with a context");
1032
1033         // Test binding with event data
1034         jQuery("#foo").live("click", true, function(e){ equals( e.data, true, "live with event data" ); });
1035         jQuery("#foo").trigger("click").die("click");
1036
1037         // Test binding with trigger data
1038         jQuery("#foo").live("click", function(e, data){ equals( data, true, "live with trigger data" ); });
1039         jQuery("#foo").trigger("click", true).die("click");
1040
1041         // Test binding with different this object
1042         jQuery("#foo").live("click", jQuery.proxy(function(e){ equals( this.foo, "bar", "live with event scope" ); }, { foo: "bar" }));
1043         jQuery("#foo").trigger("click").die("click");
1044
1045         // Test binding with different this object, event data, and trigger data
1046         jQuery("#foo").live("click", true, jQuery.proxy(function(e, data){
1047                 equals( e.data, true, "live with with different this object, event data, and trigger data" );
1048                 equals( this.foo, "bar", "live with with different this object, event data, and trigger data" ); 
1049                 equals( data, true, "live with with different this object, event data, and trigger data")
1050         }, { foo: "bar" }));
1051         jQuery("#foo").trigger("click", true).die("click");
1052
1053         // Verify that return false prevents default action
1054         jQuery("#anchor2").live("click", function(){ return false; });
1055         var hash = window.location.hash;
1056         jQuery("#anchor2").trigger("click");
1057         equals( window.location.hash, hash, "return false worked" );
1058         jQuery("#anchor2").die("click");
1059
1060         // Verify that .preventDefault() prevents default action
1061         jQuery("#anchor2").live("click", function(e){ e.preventDefault(); });
1062         var hash = window.location.hash;
1063         jQuery("#anchor2").trigger("click");
1064         equals( window.location.hash, hash, "e.preventDefault() worked" );
1065         jQuery("#anchor2").die("click");
1066
1067         // Test binding the same handler to multiple points
1068         var called = 0;
1069         function callback(){ called++; return false; }
1070
1071         jQuery("#nothiddendiv").live("click", callback);
1072         jQuery("#anchor2").live("click", callback);
1073
1074         jQuery("#nothiddendiv").trigger("click");
1075         equals( called, 1, "Verify that only one click occurred." );
1076
1077         called = 0;
1078         jQuery("#anchor2").trigger("click");
1079         equals( called, 1, "Verify that only one click occurred." );
1080
1081         // Make sure that only one callback is removed
1082         jQuery("#anchor2").die("click", callback);
1083
1084         called = 0;
1085         jQuery("#nothiddendiv").trigger("click");
1086         equals( called, 1, "Verify that only one click occurred." );
1087
1088         called = 0;
1089         jQuery("#anchor2").trigger("click");
1090         equals( called, 0, "Verify that no click occurred." );
1091
1092         // Make sure that it still works if the selector is the same,
1093         // but the event type is different
1094         jQuery("#nothiddendiv").live("foo", callback);
1095
1096         // Cleanup
1097         jQuery("#nothiddendiv").die("click", callback);
1098
1099         called = 0;
1100         jQuery("#nothiddendiv").trigger("click");
1101         equals( called, 0, "Verify that no click occurred." );
1102
1103         called = 0;
1104         jQuery("#nothiddendiv").trigger("foo");
1105         equals( called, 1, "Verify that one foo occurred." );
1106
1107         // Cleanup
1108         jQuery("#nothiddendiv").die("foo", callback);
1109         
1110         // Make sure we don't loose the target by DOM modifications
1111         // after the bubble already reached the liveHandler
1112         var livec = 0, elemDiv = jQuery("#nothiddendivchild").html('<span></span>').get(0);
1113         
1114         jQuery("#nothiddendivchild").live("click", function(e){ jQuery("#nothiddendivchild").html(''); });
1115         jQuery("#nothiddendivchild").live("click", function(e){ if(e.target) {livec++;} });
1116         
1117         jQuery("#nothiddendiv span").click();
1118         equals( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
1119         equals( livec, 1, "Verify that second handler occurred even with nuked target." );
1120         
1121         // Cleanup
1122         jQuery("#nothiddendivchild").die("click");
1123
1124         // Verify that .live() ocurs and cancel buble in the same order as
1125         // we would expect .bind() and .click() without delegation
1126         var lived = 0, livee = 0;
1127         
1128         // bind one pair in one order
1129         jQuery('span#liveSpan1 a').live('click', function(){ lived++; return false; });
1130         jQuery('span#liveSpan1').live('click', function(){ livee++; });
1131
1132         jQuery('span#liveSpan1 a').click();
1133         equals( lived, 1, "Verify that only one first handler occurred." );
1134         equals( livee, 0, "Verify that second handler doesn't." );
1135
1136         // and one pair in inverse
1137         jQuery('span#liveSpan2').live('click', function(){ livee++; });
1138         jQuery('span#liveSpan2 a').live('click', function(){ lived++; return false; });
1139
1140         lived = 0;
1141         livee = 0;
1142         jQuery('span#liveSpan2 a').click();
1143         equals( lived, 1, "Verify that only one first handler occurred." );
1144         equals( livee, 0, "Verify that second handler doesn't." );
1145         
1146         // Cleanup
1147         jQuery("span#liveSpan1 a").die("click")
1148         jQuery("span#liveSpan1").die("click");
1149         jQuery("span#liveSpan2 a").die("click");
1150         jQuery("span#liveSpan2").die("click");
1151         
1152         // Test this, target and currentTarget are correct
1153         jQuery('span#liveSpan1').live('click', function(e){ 
1154                 equals( this.id, 'liveSpan1', 'Check the this within a live handler' );
1155                 equals( e.currentTarget.id, 'liveSpan1', 'Check the event.currentTarget within a live handler' );
1156                 equals( e.target.nodeName.toUpperCase(), 'A', 'Check the event.target within a live handler' );
1157         });
1158         
1159         jQuery('span#liveSpan1 a').click();
1160         
1161         jQuery('span#liveSpan1').die('click');
1162
1163         // Work with deep selectors
1164         livee = 0;
1165
1166         function clickB(){ livee++; }
1167
1168         jQuery("#nothiddendiv div").live("click", function(){ livee++; });
1169         jQuery("#nothiddendiv div").live("click", clickB);
1170         jQuery("#nothiddendiv div").live("mouseover", function(){ livee++; });
1171
1172         equals( livee, 0, "No clicks, deep selector." );
1173
1174         livee = 0;
1175         jQuery("#nothiddendivchild").trigger("click");
1176         equals( livee, 2, "Click, deep selector." );
1177
1178         livee = 0;
1179         jQuery("#nothiddendivchild").trigger("mouseover");
1180         equals( livee, 1, "Mouseover, deep selector." );
1181
1182         jQuery("#nothiddendiv div").die("mouseover");
1183
1184         livee = 0;
1185         jQuery("#nothiddendivchild").trigger("click");
1186         equals( livee, 2, "Click, deep selector." );
1187
1188         livee = 0;
1189         jQuery("#nothiddendivchild").trigger("mouseover");
1190         equals( livee, 0, "Mouseover, deep selector." );
1191
1192         jQuery("#nothiddendiv div").die("click", clickB);
1193
1194         livee = 0;
1195         jQuery("#nothiddendivchild").trigger("click");
1196         equals( livee, 1, "Click, deep selector." );
1197
1198         jQuery("#nothiddendiv div").die("click");
1199
1200         jQuery("#nothiddendiv div").live("blur", function(){
1201                 ok( true, "Live div trigger blur." );
1202         });
1203
1204         jQuery("#nothiddendiv div").trigger("blur");
1205
1206         jQuery("#nothiddendiv div").die("blur");
1207 });
1208
1209 test("die all bound events", function(){
1210         expect(1);
1211
1212         var count = 0;
1213         var div = jQuery("div#nothiddendivchild");
1214
1215         div.live("click submit", function(){ count++; });
1216         div.die();
1217
1218         div.trigger("click");
1219         div.trigger("submit");
1220
1221         equals( count, 0, "Make sure no events were triggered." );
1222 });
1223
1224 test("live with multiple events", function(){
1225         expect(1);
1226
1227         var count = 0;
1228         var div = jQuery("div#nothiddendivchild");
1229
1230         div.live("click submit", function(){ count++; });
1231
1232         div.trigger("click");
1233         div.trigger("submit");
1234
1235         equals( count, 2, "Make sure both the click and submit were triggered." );
1236 });
1237
1238 test("live with namespaces", function(){
1239         expect(12);
1240
1241         var count1 = 0, count2 = 0;
1242
1243         jQuery("#liveSpan1").live("foo.bar", function(e){
1244                 count1++;
1245         });
1246
1247         jQuery("#liveSpan1").live("foo.zed", function(e){
1248                 count2++;
1249         });
1250
1251         jQuery("#liveSpan1").trigger("foo.bar");
1252         equals( count1, 1, "Got live foo.bar" );
1253         equals( count2, 0, "Got live foo.bar" );
1254
1255         count1 = 0, count2 = 0;
1256
1257         jQuery("#liveSpan1").trigger("foo.zed");
1258         equals( count1, 0, "Got live foo.zed" );
1259         equals( count2, 1, "Got live foo.zed" );
1260
1261         //remove one
1262         count1 = 0, count2 = 0;
1263
1264         jQuery("#liveSpan1").die("foo.zed");
1265         jQuery("#liveSpan1").trigger("foo.bar");
1266
1267         equals( count1, 1, "Got live foo.bar after dieing foo.zed" );
1268         equals( count2, 0, "Got live foo.bar after dieing foo.zed" );
1269
1270         count1 = 0, count2 = 0;
1271
1272         jQuery("#liveSpan1").trigger("foo.zed");
1273         equals( count1, 0, "Got live foo.zed" );
1274         equals( count2, 0, "Got live foo.zed" );
1275
1276         //remove the other
1277         jQuery("#liveSpan1").die("foo.bar");
1278
1279         count1 = 0, count2 = 0;
1280
1281         jQuery("#liveSpan1").trigger("foo.bar");
1282         equals( count1, 0, "Did not respond to foo.bar after dieing it" );
1283         equals( count2, 0, "Did not respond to foo.bar after dieing it" );
1284
1285         jQuery("#liveSpan1").trigger("foo.zed");
1286         equals( count1, 0, "Did not trigger foo.zed again" );
1287         equals( count2, 0, "Did not trigger foo.zed again" );
1288 });
1289
1290 test("live with change", function(){
1291         expect(8);
1292
1293         var selectChange = 0, checkboxChange = 0;
1294         
1295         var select = jQuery("select[name='S1']")
1296         select.live("change", function() {
1297                 selectChange++;
1298         });
1299         
1300         var checkbox = jQuery("#check2"), 
1301                 checkboxFunction = function(){
1302                         checkboxChange++;
1303                 }
1304         checkbox.live("change", checkboxFunction);
1305         
1306         // test click on select
1307
1308         // second click that changed it
1309         selectChange = 0;
1310         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1311         select.trigger("change");
1312         equals( selectChange, 1, "Change on click." );
1313         
1314         // test keys on select
1315         selectChange = 0;
1316         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1317         select.trigger("change");
1318         equals( selectChange, 1, "Change on keyup." );
1319         
1320         // test click on checkbox
1321         checkbox.trigger("change");
1322         equals( checkboxChange, 1, "Change on checkbox." );
1323         
1324         // test blur/focus on text
1325         var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
1326         text.live("change", function() {
1327                 textChange++;
1328         });
1329
1330         text.val(oldTextVal+"foo");
1331         text.trigger("change");
1332         equals( textChange, 1, "Change on text input." );
1333
1334         text.val(oldTextVal);
1335         text.die("change");
1336         
1337         // test blur/focus on password
1338         var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
1339         password.live("change", function() {
1340                 passwordChange++;
1341         });
1342
1343         password.val(oldPasswordVal + "foo");
1344         password.trigger("change");
1345         equals( passwordChange, 1, "Change on password input." );
1346
1347         password.val(oldPasswordVal);
1348         password.die("change");
1349         
1350         // make sure die works
1351         
1352         // die all changes
1353         selectChange = 0;
1354         select.die("change");
1355         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1356         select.trigger("change");
1357         equals( selectChange, 0, "Die on click works." );
1358
1359         selectChange = 0;
1360         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1361         select.trigger("change");
1362         equals( selectChange, 0, "Die on keyup works." );
1363         
1364         // die specific checkbox
1365         checkbox.die("change", checkboxFunction);
1366         checkbox.trigger("change");
1367         equals( checkboxChange, 1, "Die on checkbox." );
1368 });
1369
1370 test("live with submit", function() {
1371         var count1 = 0, count2 = 0;
1372         
1373         jQuery("#testForm").live("submit", function(ev) {
1374                 count1++;
1375                 ev.preventDefault();
1376         });
1377
1378         jQuery("body").live("submit", function(ev) {
1379                 count2++;
1380                 ev.preventDefault();
1381         });
1382
1383         jQuery("#testForm input[name=sub1]").submit();
1384         equals( count1, 1, "Verify form submit." );
1385         equals( count2, 1, "Verify body submit." );
1386         
1387         jQuery("#testForm").die("submit");
1388         jQuery("body").die("submit");
1389 });
1390
1391 test("live with special events", function() {
1392         expect(13);
1393
1394         jQuery.event.special.foo = {
1395                 setup: function( data, namespaces, handler ) {
1396                         ok( true, "Setup run." );
1397                 },
1398                 teardown: function( namespaces ) {
1399                         ok( true, "Teardown run." );
1400                 },
1401                 add: function( handleObj ) {
1402                         ok( true, "Add run." );
1403                 },
1404                 remove: function( handleObj ) {
1405                         ok( true, "Remove run." );
1406                 },
1407                 _default: function( event ) {
1408                         ok( true, "Default run." );
1409                 }
1410         };
1411
1412         // Run: setup, add
1413         jQuery("#liveSpan1").live("foo.a", function(e){
1414                 ok( true, "Handler 1 run." );
1415         });
1416
1417         // Run: add
1418         jQuery("#liveSpan1").live("foo.b", function(e){
1419                 ok( true, "Handler 2 run." );
1420         });
1421
1422         // Run: Handler 1, Handler 2, Default
1423         jQuery("#liveSpan1").trigger("foo");
1424
1425         // Run: Handler 1, Default
1426         // TODO: Namespace doesn't trigger default (?)
1427         jQuery("#liveSpan1").trigger("foo.a");
1428
1429         // Run: remove
1430         jQuery("#liveSpan1").die("foo.a");
1431
1432         // Run: Handler 2, Default
1433         jQuery("#liveSpan1").trigger("foo");
1434
1435         // Run: remove, teardown
1436         jQuery("#liveSpan1").die("foo");
1437
1438         delete jQuery.event.special.foo;
1439 });
1440
1441 test(".delegate()/.undelegate()", function() {
1442         expect(65);
1443
1444         var submit = 0, div = 0, livea = 0, liveb = 0;
1445
1446         jQuery("#body").delegate("div", "submit", function(){ submit++; return false; });
1447         jQuery("#body").delegate("div", "click", function(){ div++; });
1448         jQuery("#body").delegate("div#nothiddendiv", "click", function(){ livea++; });
1449         jQuery("#body").delegate("div#nothiddendivchild", "click", function(){ liveb++; });
1450
1451         // Nothing should trigger on the body
1452         jQuery("body").trigger("click");
1453         equals( submit, 0, "Click on body" );
1454         equals( div, 0, "Click on body" );
1455         equals( livea, 0, "Click on body" );
1456         equals( liveb, 0, "Click on body" );
1457
1458         // This should trigger two events
1459         submit = 0, div = 0, livea = 0, liveb = 0;
1460         jQuery("div#nothiddendiv").trigger("click");
1461         equals( submit, 0, "Click on div" );
1462         equals( div, 1, "Click on div" );
1463         equals( livea, 1, "Click on div" );
1464         equals( liveb, 0, "Click on div" );
1465
1466         // This should trigger three events (w/ bubbling)
1467         submit = 0, div = 0, livea = 0, liveb = 0;
1468         jQuery("div#nothiddendivchild").trigger("click");
1469         equals( submit, 0, "Click on inner div" );
1470         equals( div, 2, "Click on inner div" );
1471         equals( livea, 1, "Click on inner div" );
1472         equals( liveb, 1, "Click on inner div" );
1473
1474         // This should trigger one submit
1475         submit = 0, div = 0, livea = 0, liveb = 0;
1476         jQuery("div#nothiddendivchild").trigger("submit");
1477         equals( submit, 1, "Submit on div" );
1478         equals( div, 0, "Submit on div" );
1479         equals( livea, 0, "Submit on div" );
1480         equals( liveb, 0, "Submit on div" );
1481
1482         // Make sure no other events were removed in the process
1483         submit = 0, div = 0, livea = 0, liveb = 0;
1484         jQuery("div#nothiddendivchild").trigger("click");
1485         equals( submit, 0, "undelegate Click on inner div" );
1486         equals( div, 2, "undelegate Click on inner div" );
1487         equals( livea, 1, "undelegate Click on inner div" );
1488         equals( liveb, 1, "undelegate Click on inner div" );
1489
1490         // Now make sure that the removal works
1491         submit = 0, div = 0, livea = 0, liveb = 0;
1492         jQuery("#body").undelegate("div#nothiddendivchild", "click");
1493         jQuery("div#nothiddendivchild").trigger("click");
1494         equals( submit, 0, "undelegate Click on inner div" );
1495         equals( div, 2, "undelegate Click on inner div" );
1496         equals( livea, 1, "undelegate Click on inner div" );
1497         equals( liveb, 0, "undelegate Click on inner div" );
1498
1499         // Make sure that the click wasn't removed too early
1500         submit = 0, div = 0, livea = 0, liveb = 0;
1501         jQuery("div#nothiddendiv").trigger("click");
1502         equals( submit, 0, "undelegate Click on inner div" );
1503         equals( div, 1, "undelegate Click on inner div" );
1504         equals( livea, 1, "undelegate Click on inner div" );
1505         equals( liveb, 0, "undelegate Click on inner div" );
1506
1507         // Make sure that stopPropgation doesn't stop live events
1508         submit = 0, div = 0, livea = 0, liveb = 0;
1509         jQuery("#body").delegate("div#nothiddendivchild", "click", function(e){ liveb++; e.stopPropagation(); });
1510         jQuery("div#nothiddendivchild").trigger("click");
1511         equals( submit, 0, "stopPropagation Click on inner div" );
1512         equals( div, 1, "stopPropagation Click on inner div" );
1513         equals( livea, 0, "stopPropagation Click on inner div" );
1514         equals( liveb, 1, "stopPropagation Click on inner div" );
1515
1516         // Make sure click events only fire with primary click
1517         submit = 0, div = 0, livea = 0, liveb = 0;
1518         var event = jQuery.Event("click");
1519         event.button = 1;
1520         jQuery("div#nothiddendiv").trigger(event);
1521
1522         equals( livea, 0, "delegate secondary click" );
1523
1524         jQuery("#body").undelegate("div#nothiddendivchild", "click");
1525         jQuery("#body").undelegate("div#nothiddendiv", "click");
1526         jQuery("#body").undelegate("div", "click");
1527         jQuery("#body").undelegate("div", "submit");
1528
1529         // Test binding with a different context
1530         var clicked = 0, container = jQuery('#main')[0];
1531         jQuery("#main").delegate("#foo", "click", function(e){ clicked++; });
1532         jQuery("div").trigger('click');
1533         jQuery("#foo").trigger('click');
1534         jQuery("#main").trigger('click');
1535         jQuery("body").trigger('click');
1536         equals( clicked, 2, "delegate with a context" );
1537
1538         // Make sure the event is actually stored on the context
1539         ok( jQuery.data(container, "events").live, "delegate with a context" );
1540
1541         // Test unbinding with a different context
1542         jQuery("#main").undelegate("#foo", "click");
1543         jQuery("#foo").trigger('click');
1544         equals( clicked, 2, "undelegate with a context");
1545
1546         // Test binding with event data
1547         jQuery("#body").delegate("#foo", "click", true, function(e){ equals( e.data, true, "delegate with event data" ); });
1548         jQuery("#foo").trigger("click");
1549         jQuery("#body").undelegate("#foo", "click");
1550
1551         // Test binding with trigger data
1552         jQuery("#body").delegate("#foo", "click", function(e, data){ equals( data, true, "delegate with trigger data" ); });
1553         jQuery("#foo").trigger("click", true);
1554         jQuery("#body").undelegate("#foo", "click");
1555
1556         // Test binding with different this object
1557         jQuery("#body").delegate("#foo", "click", jQuery.proxy(function(e){ equals( this.foo, "bar", "delegate with event scope" ); }, { foo: "bar" }));
1558         jQuery("#foo").trigger("click");
1559         jQuery("#body").undelegate("#foo", "click");
1560
1561         // Test binding with different this object, event data, and trigger data
1562         jQuery("#body").delegate("#foo", "click", true, jQuery.proxy(function(e, data){
1563                 equals( e.data, true, "delegate with with different this object, event data, and trigger data" );
1564                 equals( this.foo, "bar", "delegate with with different this object, event data, and trigger data" ); 
1565                 equals( data, true, "delegate with with different this object, event data, and trigger data")
1566         }, { foo: "bar" }));
1567         jQuery("#foo").trigger("click", true);
1568         jQuery("#body").undelegate("#foo", "click");
1569
1570         // Verify that return false prevents default action
1571         jQuery("#body").delegate("#anchor2", "click", function(){ return false; });
1572         var hash = window.location.hash;
1573         jQuery("#anchor2").trigger("click");
1574         equals( window.location.hash, hash, "return false worked" );
1575         jQuery("#body").undelegate("#anchor2", "click");
1576
1577         // Verify that .preventDefault() prevents default action
1578         jQuery("#body").delegate("#anchor2", "click", function(e){ e.preventDefault(); });
1579         var hash = window.location.hash;
1580         jQuery("#anchor2").trigger("click");
1581         equals( window.location.hash, hash, "e.preventDefault() worked" );
1582         jQuery("#body").undelegate("#anchor2", "click");
1583
1584         // Test binding the same handler to multiple points
1585         var called = 0;
1586         function callback(){ called++; return false; }
1587
1588         jQuery("#body").delegate("#nothiddendiv", "click", callback);
1589         jQuery("#body").delegate("#anchor2", "click", callback);
1590
1591         jQuery("#nothiddendiv").trigger("click");
1592         equals( called, 1, "Verify that only one click occurred." );
1593
1594         called = 0;
1595         jQuery("#anchor2").trigger("click");
1596         equals( called, 1, "Verify that only one click occurred." );
1597
1598         // Make sure that only one callback is removed
1599         jQuery("#body").undelegate("#anchor2", "click", callback);
1600
1601         called = 0;
1602         jQuery("#nothiddendiv").trigger("click");
1603         equals( called, 1, "Verify that only one click occurred." );
1604
1605         called = 0;
1606         jQuery("#anchor2").trigger("click");
1607         equals( called, 0, "Verify that no click occurred." );
1608
1609         // Make sure that it still works if the selector is the same,
1610         // but the event type is different
1611         jQuery("#body").delegate("#nothiddendiv", "foo", callback);
1612
1613         // Cleanup
1614         jQuery("#body").undelegate("#nothiddendiv", "click", callback);
1615
1616         called = 0;
1617         jQuery("#nothiddendiv").trigger("click");
1618         equals( called, 0, "Verify that no click occurred." );
1619
1620         called = 0;
1621         jQuery("#nothiddendiv").trigger("foo");
1622         equals( called, 1, "Verify that one foo occurred." );
1623
1624         // Cleanup
1625         jQuery("#body").undelegate("#nothiddendiv", "foo", callback);
1626         
1627         // Make sure we don't loose the target by DOM modifications
1628         // after the bubble already reached the liveHandler
1629         var livec = 0, elemDiv = jQuery("#nothiddendivchild").html('<span></span>').get(0);
1630         
1631         jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ jQuery("#nothiddendivchild").html(''); });
1632         jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ if(e.target) {livec++;} });
1633         
1634         jQuery("#nothiddendiv span").click();
1635         equals( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
1636         equals( livec, 1, "Verify that second handler occurred even with nuked target." );
1637         
1638         // Cleanup
1639         jQuery("#body").undelegate("#nothiddendivchild", "click");
1640
1641         // Verify that .live() ocurs and cancel buble in the same order as
1642         // we would expect .bind() and .click() without delegation
1643         var lived = 0, livee = 0;
1644         
1645         // bind one pair in one order
1646         jQuery("#body").delegate('span#liveSpan1 a', 'click', function(){ lived++; return false; });
1647         jQuery("#body").delegate('span#liveSpan1', 'click', function(){ livee++; });
1648
1649         jQuery('span#liveSpan1 a').click();
1650         equals( lived, 1, "Verify that only one first handler occurred." );
1651         equals( livee, 0, "Verify that second handler doesn't." );
1652
1653         // and one pair in inverse
1654         jQuery("#body").delegate('span#liveSpan2', 'click', function(){ livee++; });
1655         jQuery("#body").delegate('span#liveSpan2 a', 'click', function(){ lived++; return false; });
1656
1657         lived = 0;
1658         livee = 0;
1659         jQuery('span#liveSpan2 a').click();
1660         equals( lived, 1, "Verify that only one first handler occurred." );
1661         equals( livee, 0, "Verify that second handler doesn't." );
1662         
1663         // Cleanup
1664         jQuery("#body").undelegate("click");
1665         
1666         // Test this, target and currentTarget are correct
1667         jQuery("#body").delegate('span#liveSpan1', 'click', function(e){ 
1668                 equals( this.id, 'liveSpan1', 'Check the this within a delegate handler' );
1669                 equals( e.currentTarget.id, 'liveSpan1', 'Check the event.currentTarget within a delegate handler' );
1670                 equals( e.target.nodeName.toUpperCase(), 'A', 'Check the event.target within a delegate handler' );
1671         });
1672         
1673         jQuery('span#liveSpan1 a').click();
1674         
1675         jQuery("#body").undelegate('span#liveSpan1', 'click');
1676
1677         // Work with deep selectors
1678         livee = 0;
1679
1680         function clickB(){ livee++; }
1681
1682         jQuery("#body").delegate("#nothiddendiv div", "click", function(){ livee++; });
1683         jQuery("#body").delegate("#nothiddendiv div", "click", clickB);
1684         jQuery("#body").delegate("#nothiddendiv div", "mouseover", function(){ livee++; });
1685
1686         equals( livee, 0, "No clicks, deep selector." );
1687
1688         livee = 0;
1689         jQuery("#nothiddendivchild").trigger("click");
1690         equals( livee, 2, "Click, deep selector." );
1691
1692         livee = 0;
1693         jQuery("#nothiddendivchild").trigger("mouseover");
1694         equals( livee, 1, "Mouseover, deep selector." );
1695
1696         jQuery("#body").undelegate("#nothiddendiv div", "mouseover");
1697
1698         livee = 0;
1699         jQuery("#nothiddendivchild").trigger("click");
1700         equals( livee, 2, "Click, deep selector." );
1701
1702         livee = 0;
1703         jQuery("#nothiddendivchild").trigger("mouseover");
1704         equals( livee, 0, "Mouseover, deep selector." );
1705
1706         jQuery("#body").undelegate("#nothiddendiv div", "click", clickB);
1707
1708         livee = 0;
1709         jQuery("#nothiddendivchild").trigger("click");
1710         equals( livee, 1, "Click, deep selector." );
1711
1712         jQuery("#body").undelegate("#nothiddendiv div", "click");
1713 });
1714
1715 test("undelegate all bound events", function(){
1716         expect(1);
1717
1718         var count = 0;
1719         var div = jQuery("#body");
1720
1721         div.delegate("div#nothiddendivchild", "click submit", function(){ count++; });
1722         div.undelegate();
1723
1724         jQuery("div#nothiddendivchild").trigger("click");
1725         jQuery("div#nothiddendivchild").trigger("submit");
1726
1727         equals( count, 0, "Make sure no events were triggered." );
1728 });
1729
1730 test("delegate with multiple events", function(){
1731         expect(1);
1732
1733         var count = 0;
1734         var div = jQuery("#body");
1735
1736         div.delegate("div#nothiddendivchild", "click submit", function(){ count++; });
1737
1738         jQuery("div#nothiddendivchild").trigger("click");
1739         jQuery("div#nothiddendivchild").trigger("submit");
1740
1741         equals( count, 2, "Make sure both the click and submit were triggered." );
1742
1743         jQuery("#body").undelegate();
1744 });
1745
1746 test("delegate with change", function(){
1747         expect(8);
1748
1749         var selectChange = 0, checkboxChange = 0;
1750         
1751         var select = jQuery("select[name='S1']");
1752         jQuery("#body").delegate("select[name='S1']", "change", function() {
1753                 selectChange++;
1754         });
1755         
1756         var checkbox = jQuery("#check2"), 
1757                 checkboxFunction = function(){
1758                         checkboxChange++;
1759                 }
1760         jQuery("#body").delegate("#check2", "change", checkboxFunction);
1761         
1762         // test click on select
1763
1764         // second click that changed it
1765         selectChange = 0;
1766         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1767         select.trigger("change");
1768         equals( selectChange, 1, "Change on click." );
1769         
1770         // test keys on select
1771         selectChange = 0;
1772         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1773         select.trigger("change");
1774         equals( selectChange, 1, "Change on keyup." );
1775         
1776         // test click on checkbox
1777         checkbox.trigger("change");
1778         equals( checkboxChange, 1, "Change on checkbox." );
1779         
1780         // test blur/focus on text
1781         var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
1782         jQuery("#body").delegate("#name", "change", function() {
1783                 textChange++;
1784         });
1785
1786         text.val(oldTextVal+"foo");
1787         text.trigger("change");
1788         equals( textChange, 1, "Change on text input." );
1789
1790         text.val(oldTextVal);
1791         jQuery("#body").die("change");
1792         
1793         // test blur/focus on password
1794         var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
1795         jQuery("#body").delegate("#name", "change", function() {
1796                 passwordChange++;
1797         });
1798
1799         password.val(oldPasswordVal + "foo");
1800         password.trigger("change");
1801         equals( passwordChange, 1, "Change on password input." );
1802
1803         password.val(oldPasswordVal);
1804         jQuery("#body").undelegate("#name", "change");
1805         
1806         // make sure die works
1807         
1808         // die all changes
1809         selectChange = 0;
1810         jQuery("#body").undelegate("select[name='S1']", "change");
1811         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1812         select.trigger("change");
1813         equals( selectChange, 0, "Die on click works." );
1814
1815         selectChange = 0;
1816         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1817         select.trigger("change");
1818         equals( selectChange, 0, "Die on keyup works." );
1819         
1820         // die specific checkbox
1821         jQuery("#body").undelegate("#check2", "change", checkboxFunction);
1822         checkbox.trigger("change");
1823         equals( checkboxChange, 1, "Die on checkbox." );
1824 });
1825
1826 test("delegate with submit", function() {
1827         var count1 = 0, count2 = 0;
1828         
1829         jQuery("#body").delegate("#testForm", "submit", function(ev) {
1830                 count1++;
1831                 ev.preventDefault();
1832         });
1833
1834         jQuery(document).delegate("body", "submit", function(ev) {
1835                 count2++;
1836                 ev.preventDefault();
1837         });
1838
1839         jQuery("#testForm input[name=sub1]").submit();
1840         equals( count1, 1, "Verify form submit." );
1841         equals( count2, 1, "Verify body submit." );
1842         
1843         jQuery("#body").undelegate();
1844         jQuery(document).undelegate();
1845 });
1846
1847 test("Non DOM element events", function() {
1848         expect(1);
1849
1850         var o = {};
1851
1852         jQuery(o).bind('nonelementobj', function(e) {
1853                 ok( true, "Event on non-DOM object triggered" );
1854         });
1855
1856         jQuery(o).trigger('nonelementobj');
1857 });
1858
1859 test("window resize", function() {
1860         expect(2);
1861
1862         jQuery(window).unbind();
1863
1864         jQuery(window).bind("resize", function(){
1865                 ok( true, "Resize event fired." );
1866         }).resize().unbind("resize");
1867
1868         ok( !jQuery(window).data("__events__"), "Make sure all the events are gone." );
1869 });
1870
1871 test("focusin bubbles", function() {
1872         //create an input and focusin on it
1873         var input = jQuery("<input/>"), order = 0;
1874
1875         input.prependTo("body");
1876
1877         jQuery("body").bind("focusin.focusinBubblesTest",function(){
1878                 equals(1,order++,"focusin on the body second")
1879         });
1880
1881         input.bind("focusin.focusinBubblesTest",function(){
1882                 equals(0,order++,"focusin on the element first")
1883         });
1884
1885         input[0].focus();
1886         input.remove();
1887
1888         jQuery("body").unbind("focusin.focusinBubblesTest");
1889 });
1890
1891 /*
1892 test("jQuery(function($) {})", function() {
1893         stop();
1894         jQuery(function($) {
1895                 equals(jQuery, $, "ready doesn't provide an event object, instead it provides a reference to the jQuery function, see http://docs.jquery.com/Events/ready#fn");
1896                 start();
1897         });
1898 });
1899
1900 test("event properties", function() {
1901         stop();
1902         jQuery("#simon1").click(function(event) {
1903                 ok( event.timeStamp, "assert event.timeStamp is present" );
1904                 start();
1905         }).click();
1906 });
1907 */