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