1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<div class="intro">
<p>This example demonstrates how to use multiple NodeList features to build a simple game.</p>
</div>
<div class="example">
{{>ducks-source}}
</div>
<h2>The HTML</h2>
```
{{>ducks-html}}
```
<h2>YUI Instance</h2>
<p>
The `use` statement doesn't include `node` because it's loaded as a requirement of transition.
</p>
```
YUI().use('transition', 'button', function(Y){
// code goes here
});
```
<h2>Setting Vars</h2>
<p>
The variable `ducks` is used for easily manipulating all the ducks at once.
We'll display various duck comments from the array `squawkTextArr` on a rotating basis.
</p>
```
var ducks = Y.all('.duck-row li'),
ducksRemaining = 10, // value for UI display
squawkTextIndex = 0, // index in the squawkTextArr to use next
squawkTextArr = [ // duck comments
'#@&~*Q!',
'Hey!?',
'911 on U!',
"U fly's down",
'duck pile!',
'Ricochets kill!',
'how sporting.',
"shoe's untied"
];
```
<h2>Initializing the Ducks</h2>
<p>
Repetitive markup is added with the `.append()` method to all the ducks in the `NodeList`.
This keeps the original markup simple and clear.
</p>
```
// append the same content for each duck <li>
ducks.append('<img src="../assets/node/images/duck.png"/><div class="squawk"><div class="text">#@&~*Q!</div><div class="small-squawk-bubble"></div></div>');
```
<p>
All the ducks in the `NodeList` are given the `set-up` class with the `.addClass()` method.
This class is found on any duck that has the state of being set up, as opposed to being knocked down.
</p>
```
// give them all the set-up state class
ducks.addClass('set-up');
```
<p>
This state could be a Boolean property, but it's handy as a class,
because a `NodeList` can be made containing the squawks of all "set up" ducks in this way,
`squawks = Y.all('.duck-row .set-up .squawk');`
as we'll see in the `makeDucksSquawk` function.
</p>
<h2>Making the Ducks Swim</h2>
<p>
This uses `transition` to make the ducks swim right to left
</p>
```
// this makes the ducks move from right to left.
// When the duck on the far left disappears from view,
// it's added to the far right end of the row.
var makeDucksSwim = function () {
var frontDuck;
// move the duck row to the left one duck space over 2 seconds
Y.one('.duck-row').transition({
easing: 'linear',
left: '-119px',
duration: 2
}, function () { // when the row finishes its right to left transition...
// remove the first duck on the left
// which has trasitioned out of view
frontDuck = Y.one('.duck-row li').remove();
// append the removed first duck onto the right end
Y.one('.duck-row').appendChild(frontDuck);
// set the position for the next makeDucksSwim()
Y.one('.duck-row').setStyle('left', '10px');
// if there are ducks remaining, make them swim again
if (ducksRemaining > 0) {
makeDucksSwim();
}
});
}
makeDucksSwim(); // this initializes the ducks swimming
```
<h2>Click Event Handler</h2>
<p>
</p>
```
// handles a click on a duck
var duckClick = function(e) {
var squawks;
// remove the squawk belonging to the duck that was clicked
e.currentTarget.one('.squawk').setStyles({'top': '-400px', 'opacity': '1'});
// makes the ducks appear to lay back when clicked
duration: 0.2,
height: '3px',
width: '133px'
});
// the clicked duck will no longer have the 'set-up' class/state
e.currentTarget.removeClass('set-up');
makeDucksSquawk(); // makes the ducks squawk
updateDucksRemaining(); // update the number of ducks still set up
};
```
<h2>Squawking Ducks</h2>
<p>
</p>
```
// this makes the duck's squawks show and hide and get various text
var makeDucksSquawk = function(){
squawks = Y.all('.duck-row .set-up .squawk'); // a NodeList of the squawks of set-up ducks
if (Y.one('#show-attitude')._node.checked) { // only have ducks squawk if the checkbox is checked
// fill voice bubbles with next text string
Y.all('.duck-row .set-up .squawk .text').setContent(squawkTextArr[squawkTextIndex]);
// increment the index to get the next squawk text
squawkTextIndex = (squawkTextIndex += 1) % (squawkTextArr.length);
top: {
delay: 0.5,
value: '0px', // drop squawks into position from hidden
duration: 0 // instant position change
},
opacity: { // fade out
delay: 3.0,
duration: 0.3,
value: 0
}
}, function(e){
// after squawks are faded out,
// move them to hidden position and set opacity to 1 again
squawks.setStyles({'top': '-400px', 'opacity': '1'});
});
}
}
```
<h2>Reset and Ducks Remaining</h2>
```
// This resets all ducks, "ducks remaining" counters, and row position
// make the duck images full height
// start them swimming
var reset = function() {
Y.all('.duck-row li img').setStyle('height', '55px');
Y.all('.duck-row li').addClass('set-up');
updateDucksRemaining();
makeDucksSwim();
}
// counts the ducks remaining, and updates the UI counter display
var updateDucksRemaining = function() {
Y.one('.ducks-remain').setContent(ducksRemaining);
}
```
<h2>Prefer `node.delegate()` over `nodelist.on()`</h2>
<p>Sometimes you need to create individual subscriptions for each Node in a
NodeList, but usually it's preferable to use
<a href="node-evt-delegation.html">event delegation</a> as shown in this example.</p>
<h2>Listeners</h2>
<p>
</p>
```
// listeners
Y.one('.duck-row').delegate('click', duckClick, 'li');
Y.one('#button-reset').on('click', reset);
```
<h2>Complete Ducks Example Source</h2>
```
{{>ducks-source}}
```