5
<title>YUI Event Delegate Tests</title>
7
<body lang="en" class="yui3-skin-sam">
11
<div id="mod-header" class="hd"><h3 class="title">H3 - Title</h3></div>
12
<div id="mod-body" class="bd">
13
<p>simple paragraph with a link <a href="#"id="firstlink">simple link</a></p>
14
<p>another paragraph with a complex link <a href="#" id="secondlink"><strong>strong within link</strong><img alt="fake image" id="fakeimage" /> - complex <span id="spanwithinlink">link</span></a></p>
20
<li id="item-1"><em>Item Type One</em></li>
21
<li id="item-2"><em>Item Type Two</em></li>
22
<li id="item-3"><em>Item Type Three</em></li>
27
<li id="list-2-li-1"><em><em>Item One</em></em></li>
28
<li id="list-2-li-2"><em>Item Two</em></li>
29
<li id="list-2-li-3"><em>Item Three</em>
31
<li id="list-3-li-1"><em>Item Three - One</em></li>
32
<li id="list-3-li-2"><em>Item Three - Two</em></li>
33
<li id="list-3-li-3"><em>Item Three - Three</em></li>
38
<div id="div-1" class="div-a">
39
<div id="div-1-1" class="div-b">
40
<div id="div-1-1-1" class="div-c"><em>Item One</em></div>
42
<div id="div-1-2" class="div-x">
44
<div id="div-1-2-1" class="div-b">
45
<em id="em-1-2-1-1">Item Two - One</em>
46
<div id="div-1-2-1-1" class="div-c"><em>Item Two - Two</em></div>
53
<div id="b" class="remove">
54
<p>Div B <em id="b2" class="remove">I'm a span!</em></p>
55
<div id="c" class="remove">
62
<script src="../../../build/yui/yui.js"></script>
63
<script src="window-focus.js"></script>
66
filter: (window.location.search.match(/[?&]filter=([^&]+)/) || [])[1] || 'min',
68
lazyEventFacade: true,
69
logExclude: { Dom: true, Selector: true, Node: true, attribute: true, base: true, event: true, widget: true}
70
}).use('console', 'test', 'event', 'event-simulate', 'window-focus', function (Y) {
72
var suite = new Y.Test.Suite("Delegate");
74
// creating the console...
75
(new Y.Console()).render();
78
Y.Event.simulate(document.getElementById(id), 'click');
81
// starting the testing process
83
// add the test cases and suites
84
suite.add(new Y.Test.Case({
86
name: "Event Delegate Tests",
88
test_simple_delegate_for_anchors: function(){
90
var foo = false, t, ct, boundEl;
92
// the detach prefix broke when delegate from converted
93
// from a custom event to a function (the function should
94
// simply delegated to the custom event)
95
// Y.delegate('foo|click', function(e) {
96
Y.delegate('click', function(e) {
100
boundEl = e.container;
105
Y.Assert.isTrue(foo, "simple delegation fails, mod1 should pickup the event and test target [firstlink]");
106
// Y.Assert.areEqual(t, Y.one('#firstlink'), "event delegate works but the target is an incorrect node, should be the matching node");
108
Y.Assert.areEqual(ct, Y.one('#firstlink'), "event delegate works but the currentTarget is an incorrect node, should be the matching node");
109
Y.Assert.areEqual(t, Y.one('#firstlink'), "event delegate works but the target is an incorrect node, should be the actual click target");
110
Y.Assert.areEqual(boundEl, Y.one('#mod1'), "event delegate works but the container property should be the bound element");
114
test_multiple_selectors: function () {
116
var foo = false, t, ct, boundEl;
118
Y.delegate('click', function(e) {
121
ct = e.currentTarget;
122
boundEl = e.container;
123
}, '#mod1', '.hd,.bd');
128
Y.Assert.areEqual(ct, Y.one('#mod-header'), "event delegate works but the matched element is an incorrect node, should be the matching node");
132
Y.Assert.areEqual(ct, Y.one('#mod-body'), "event delegate works but the matched element is an incorrect node, should be the matching node");
136
test_filter_function: function () {
140
handle = Y.delegate('click', function (e) {
143
}, '#mod1', function (target, e) {
144
return target.get('tagName').toLowerCase() === 'a';
147
click('spanwithinlink');
149
Y.Assert.areSame(1, count);
154
test_filter_function_for_focus: function () {
158
if (Y.isWindowInFocus()) {
159
handle = Y.delegate('focus', function (e) {
161
}, '#mod1', function (target, e) {
162
return target.get('tagName').toLowerCase() === 'a';
165
Y.one('#spanwithinlink').focus();
166
Y.one('#fakeimage').focus();
167
Y.one('#secondlink').focus();
169
Y.Assert.areSame(1, count);
173
Y.log("Window is not focused. Can't properly test.",
174
"warn", "TestRunner");
178
test_document_as_container: function () {
180
var foo = false, t, ct, boundEl;
182
Y.delegate('click', function(e) {
185
ct = e.currentTarget;
186
boundEl = e.container;
187
}, Y.one('#mod1').get('ownerDocument'), 'a');
191
Y.Assert.isTrue(foo, "simple delegation fails, mod1 should pickup the event and test target [firstlink]");
193
Y.Assert.areEqual(ct, Y.one('#firstlink'), "event delegate works but the currentTarget is an incorrect node, should be the matching node");
194
Y.Assert.areEqual(t, Y.one('#firstlink'), "event delegate works but the target is an incorrect node, should be the actual click target");
195
Y.Assert.areEqual(boundEl, Y.one('#mod1').get('ownerDocument'), "event delegate works but the container property should be the bound element");
199
test_checking_delegation_target: function(){
201
var foo = false, t, ct, boundEl;
203
Y.delegate('click', function(e) {
206
ct = e.currentTarget;
207
boundEl = e.container;
212
Y.Assert.isTrue(foo, "delegation fails for an image within an anchor, mod1 should pickup the event and test target [secondlink]");
213
// in this case, the target should be the anchor, and not the image
214
// Y.Assert.areEqual(t, Y.one('#secondlink'), "event delegate works but the target is an incorrect node, should be the matching node");
216
// this has been changed. the target is unchanged, the anchor is
218
Y.Assert.areEqual(ct, Y.one('#secondlink'), "event delegate works but the currentTarget is an incorrect node, should be the matching node");
219
Y.Assert.areEqual(t, Y.one('#fakeimage'), "event delegate works but the target is an incorrect node, should be the actual click target");
220
Y.Assert.areEqual(boundEl, Y.one('#mod1'), "event delegate works but the container property should be the bound element");
224
test_including_container_in_selector: function(){
228
Y.delegate('click', function(e) {
231
}, '#mod1', '#mod1 a');
235
Y.Assert.isFalse(foo, "delegation fails, the container (specified in the on) can not be part of the selectors");
239
test_targeting_container_without_selectors: function(){
243
Y.delegate('click', function(e) {
250
Y.Assert.isFalse(foo, "delegation fails, delegation without at least one selector should never trigger an event");
253
test_multiple_selectors_one_match: function(){
257
Y.delegate('click', function(e) {
260
}, '#mod1', 'a,a span');
264
Y.Assert.isTrue(foo, "multiple selectors fails, delegate should be able to match different selectors");
265
Y.Assert.areEqual(t, Y.one('#firstlink'), "event delegate works but the target is an incorrect node, should be the matching selector");
269
test_multiple_delegate_matches: function(){
271
var foo1 = false, foo2 = false, t1, t2, ct1, ct2;
273
Y.delegate('click', function(e) {
276
ct1 = e.currentTarget;
279
Y.delegate('click', function(e) {
282
ct2 = e.currentTarget;
283
}, '#mod1', 'a span');
285
click('spanwithinlink');
287
Y.Assert.isTrue(foo1, "first match fail, delegate should be able to match [a]");
288
Y.Assert.isTrue(foo2, "second match fail, delegate should be able to match [a span]");
289
Y.Assert.areEqual(ct1, Y.one('#secondlink'), "event delegate works but the currentTarget is an incorrect node, should be the matching selector");
290
Y.Assert.areEqual(t1, Y.one('#spanwithinlink'), "event delegate works but the target is an incorrect node, should be the clicked node");
291
Y.Assert.areEqual(ct2, Y.one('#spanwithinlink'), "event delegate works but the target is an incorrect node, should be the matching selector");
292
Y.Assert.areEqual(t2, Y.one('#spanwithinlink'), "event delegate works but the target is an incorrect node, should be the clicked");
296
test_bubble_up_after_delegate: function(){
300
t1, t2, ct1, ct2, container1, container2, this1, this2;
302
Y.delegate('click', function(e) {
305
ct1 = e.currentTarget;
306
container1 = e.container;
310
Y.on('click', function(e) {
313
ct2 = e.currentTarget;
314
container2 = e.container;
318
click('spanwithinlink');
320
Y.Assert.isTrue(foo1, "first match fail, delegate should be able to match [a]");
321
Y.Assert.isTrue(foo2, "second match fail, the event doesn't bubble up after the delegate routine");
323
// Y.Assert.areEqual(t1, Y.one('#secondlink'), "event delegate works but the target is an incorrect node, should be the matching selector");
324
Y.Assert.areEqual(ct1, Y.one('#secondlink'), "event delegate works but the currentTarget is an incorrect node, should be the matching selector");
325
Y.Assert.areEqual(t1, Y.one('#spanwithinlink'), "event delegate works but the target is an incorrect node, should be the actual target");
328
Y.Assert.areEqual(t2, Y.one('#spanwithinlink'), "event delegate works but it doesn't restore e.target to the original value.");
330
Y.Assert.areSame(ct2, Y.one('#doc'));
331
Y.Assert.areSame(container1, Y.one('#mod1'));
332
Y.Assert.isUndefined(container2);
333
Y.Assert.areSame(this1, Y.one('#secondlink'));
334
Y.Assert.areSame(this2, Y.one('#doc'));
337
test_bubble_up_after_delegate_halt: function(){
339
var foo1 = false, foo2 = false;
341
Y.delegate('click', function(e) {
346
Y.on('click', function(e) {
350
click('spanwithinlink');
352
Y.Assert.isTrue(foo1, "first match fail, delegate should be able to match [a]");
353
Y.Assert.isFalse(foo2, "the listener for 'doc' got executed, which means that e.halt fails during the delegate routine");
356
test_direct_descendant_combinator: function () {
360
Y.one("#list-2").delegate("click", function (e) {
361
matchID = this.get("id");
364
click('list-3-li-1');
366
Y.Assert.areEqual('list-2-li-3', matchID, "The currentTarget is an incorrect node, should be the matching node.");
371
Y.one("#div-1").delegate("click", function (e) {
372
matchID = this.get("id");
377
Y.Assert.areEqual('div-1-1', matchID, "The currentTarget is an incorrect node, should be the matching node.");
384
Y.Assert.isNull(matchID, "The currentTarget is an incorrect node, should be the matching node.");
388
test_multiple_matches_in_subtree: function () {
391
Y.delegate('click', function (e) {
392
ids.push(this.get('id'));
395
Y.Event.simulate(Y.one('#div-1-2-1-1 em')._node, 'click');
397
Y.Assert.areSame(4, ids.length, "Delegate handler should have fired three times, once for each div in #div-1");
398
Y.Assert.areSame('div-1-2-1-1', ids[0], "First delegate callback should be from the deepest div in the subtree");
399
Y.Assert.areSame('div-1-2-1', ids[1]);
400
Y.Assert.areSame('div-1-2', ids[2]);
401
Y.Assert.areSame('div-1', ids[3]);
404
test_removing_parent_in_subscriber: function () {
407
Y.one('#a').delegate('click', function (e) {
408
this.get('parentNode').remove();
414
Y.Assert.areSame(2, count);
417
test_successful_purge: function () {
419
var bHandler1Called = false,
420
bHandler2Called = false;
422
Y.delegate('click', function(e) {
423
bHandler1Called = true;
426
Y.Event.purgeElement('#mod1');
428
// Test #1: Make sure first handler is not called after
429
// calling Y.Event.purgeElement
433
Y.Assert.isFalse(bHandler1Called, "No delegated listeners should be called after a call to Y.Event.purgeElement");
436
// Test #2: Make sure second handler is called after
437
// calling Y.Event.purgeElement
439
Y.delegate('click', function(e) {
440
bHandler2Called = true;
445
Y.Assert.isFalse(bHandler1Called, "The first listener should not be be called.");
446
Y.Assert.isTrue(bHandler2Called, "The second delegated listener should be called.");
448
bHandler1Called = false;
449
bHandler2Called = false;
451
// Test #3: Make sure first handler is not called after
452
// calling Y.Event.purgeElement and passing in a type
453
Y.Event.purgeElement('#mod1', false, 'click');
457
Y.Assert.isFalse(bHandler2Called, "The second listener should not be be called.");
459
// Test #4: Make sure that it is possible to delegate
460
// a listener to a new element with the same id of
461
// an element that used to exist in the DOM.
463
bHandler1Called = false;
464
bHandler2Called = false;
466
Y.delegate("click", function () {
467
bHandler1Called = true;
468
}, "#list-1", ">li");
470
Y.Event.purgeElement('#list-1');
472
Y.one("#container").setContent('<ul id="list-1"><li id="item-1"><em>Item Type One</em></li><li id="item-2"><em>Item Type Two</em></li><li id="item-3"><em>Item Type Three</em></li></ul>');
474
Y.delegate("click", function () {
475
bHandler2Called = true;
476
}, "#list-1", ">li");
480
Y.Assert.isFalse(bHandler1Called, "The first listener should not be be called.");
481
Y.Assert.isTrue(bHandler2Called, "The second delegated listener should be called.");
485
test_successful_detach: function () {
487
var bHandler1Called = false,
488
bHandler2Called = false;
490
var handle = Y.delegate('click', function(e) {
491
bHandler1Called = true;
496
// Test #1: Make sure first handler is not called after
501
Y.Assert.isFalse(bHandler1Called, "Listener should not be called after being detached.");
504
// Test #2: Make sure second handler is called after
505
// detaching the first.
507
Y.delegate('click', function(e) {
508
bHandler2Called = true;
513
Y.Assert.isFalse(bHandler1Called, "The first listener should not be be called.");
514
Y.Assert.isTrue(bHandler2Called, "The second delegated listener should be called.");
517
// Test #3: Make sure that it is possible to delegate
518
// a listener to a new element with the same id of
519
// an element that used to exist in the DOM.
521
bHandler1Called = false;
522
bHandler2Called = false;
524
handle = Y.delegate("click", function () {
525
bHandler1Called = true;
526
}, "#list-1", ">li");
530
Y.one("#container").setContent('<ul id="list-1"><li id="item-1"><em>Item Type One</em></li><li id="item-2"><em>Item Type Two</em></li><li id="item-3"><em>Item Type Three</em></li></ul>');
532
Y.delegate("click", function () {
533
bHandler2Called = true;
534
}, "#list-1", ">li");
538
Y.Assert.isFalse(bHandler1Called, "The first listener should not be be called.");
539
Y.Assert.isTrue(bHandler2Called, "The second delegated listener should be called.");
543
"Y.delegate('cat|type') should subscribe event": function () {
548
handle = Y.delegate(cat + "|click", function () {
550
}, '#container', 'li');
554
Y.Assert.areSame(1, count);
560
Y.Assert.areSame(1, count, "category sub did not detach with handle");
563
"node.delegate('cat|type') should subscribe event": function () {
568
handle = Y.one('#container').delegate(cat + "|click", function () {
574
Y.Assert.areSame(1, count);
580
Y.Assert.areSame(1, count, "category sub did not detach with handle");
583
"node.detach('cat|type', fn) should detach delegate": function () {
585
target = Y.one("#container"),
589
function increment() {
593
handle = target.delegate(cat + "|click", increment, 'li');
597
Y.Assert.areSame(1, count);
599
target.detach(cat + '|click', increment);
603
Y.Assert.areSame(1, count);
606
"node.detach('cat|type') should detach delegate": function () {
608
target = Y.one("#container"),
612
function increment() {
616
handle = target.delegate(cat + "|click", increment, 'li');
620
Y.Assert.areSame(1, count);
622
target.detach(cat + '|click');
626
Y.Assert.areSame(1, count);
629
"node.detach('cat|*') should detach delegate": function () {
631
target = Y.one("#container"),
635
function increment() {
639
handle = target.delegate(cat + "|click", increment, 'li');
643
Y.Assert.areSame(1, count);
645
target.detach(cat + '|*');
649
Y.Assert.areSame(1, count);
652
testPassingObjectForMultipleSubscriptions: function () {
659
function mousedowned() {
663
Y.one('#div-1').delegate({
665
mousedown: mousedowned
668
Y.Event.simulate(document.getElementById('em-1-2-1-1'), 'mousedown');
671
Y.Assert.isTrue(clickOk);
672
Y.Assert.isTrue(mousedownOk);
675
testThisObjOverrideWithObjectSubscription: function () {
678
Y.one('#div-1').delegate({
682
}, 'em', { foo: true });
686
Y.Assert.isObject(thisObj);
687
Y.Assert.isTrue(thisObj.foo);
690
testPassingExtraArgsWithObjectSubscription: function () {
693
Y.one('#div-1').delegate({
694
click: function (e, extraArg) {
697
}, 'em', null, "extra arg");
701
Y.Assert.areSame("extra arg", arg);
704
testDetachingObjectSubscriptionViaHandle: function () {
708
handle = Y.one('#div-1').delegate({
709
click: function (e, extraArg) {
716
Y.Assert.areSame(1, count);
722
Y.Assert.areSame(1, count);
725
testPassingArrayForMultipleSubscriptions: function () {
728
Y.one('#div-1').delegate(['click', 'mousedown'], function () {
732
Y.Event.simulate(document.getElementById('em-1-2-1-1'), 'mousedown');
735
Y.Assert.areSame(2, count);
740
* Other things that I consider should be tested in the future:
741
* - stopping the event, verifying the event ourside of the container
742
* - stopping the event and verify what happen with multiple matches
747
suite.add(new Y.Test.Case({
750
// Existing unfixed bugs
753
//test_filter_function_for_focus_from_body: 2529142,
754
//"stopPropagation should stop multiple matches": 2529388
758
test_filter_function_for_focus_from_body: function () {
762
if (Y.isWindowInFocus()) {
763
handle = Y.one('body').delegate('focus', function (e) {
768
Y.one('#firstlink').focus();
770
Y.Assert.areSame(1, count);
772
Y.log("Window is not focused. Can't properly test.",
773
"warn", "TestRunner");
777
"stopPropagation should stop multiple matches": function () {
783
handle = Y.delegate('click', function (e) {
792
click('list-3-li-2');
794
Y.Assert.isTrue((count > 1));
799
click('list-3-li-2');
801
Y.Assert.areSame(1, count);
806
click('list-3-li-2');
808
Y.Assert.areSame(1, count);
813
Y.Test.Runner.setName("Delegate");
814
Y.Test.Runner.add(suite);