adhearsion 0.7.6 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.version +1 -1
  2. data/CHANGELOG +43 -25
  3. data/Rakefile +0 -5
  4. data/TODO +51 -2
  5. data/ahn +2 -1
  6. data/apps/default/Rakefile +16 -7
  7. data/apps/default/config/adhearsion.yml +22 -1
  8. data/apps/default/config/helpers/manager_proxy.yml +1 -0
  9. data/apps/default/config/helpers/micromenus/images/arrow-off.gif +0 -0
  10. data/apps/default/config/helpers/micromenus/images/arrow-on.gif +0 -0
  11. data/apps/default/config/helpers/micromenus/images/error.gif +0 -0
  12. data/apps/default/config/helpers/micromenus/images/folder-off.gif +0 -0
  13. data/apps/default/config/helpers/micromenus/images/folder-on.gif +0 -0
  14. data/apps/default/config/helpers/micromenus/images/folder.png +0 -0
  15. data/apps/default/config/helpers/micromenus/images/ggbridge.jpg +0 -0
  16. data/apps/default/config/helpers/micromenus/images/green.png +0 -0
  17. data/apps/default/config/helpers/micromenus/images/microbrowser.bg.gif +0 -0
  18. data/apps/default/config/helpers/micromenus/images/red.png +0 -0
  19. data/apps/default/config/helpers/micromenus/images/url-off.gif +0 -0
  20. data/apps/default/config/helpers/micromenus/images/url-on.gif +0 -0
  21. data/apps/default/config/helpers/micromenus/images/yellow.png +0 -0
  22. data/apps/default/config/helpers/micromenus/javascripts/animation.js +1341 -0
  23. data/apps/default/config/helpers/micromenus/javascripts/carousel.js +1238 -0
  24. data/apps/default/config/helpers/micromenus/javascripts/columnav.js +306 -0
  25. data/apps/default/config/helpers/micromenus/javascripts/connection.js +965 -0
  26. data/apps/default/config/helpers/micromenus/javascripts/container.js +4727 -0
  27. data/apps/default/config/helpers/micromenus/javascripts/container_core.js +2915 -0
  28. data/apps/default/config/helpers/micromenus/javascripts/dom.js +892 -0
  29. data/apps/default/config/helpers/micromenus/javascripts/dragdrop.js +2921 -907
  30. data/apps/default/config/helpers/micromenus/javascripts/event.js +1771 -0
  31. data/apps/default/config/helpers/micromenus/javascripts/yahoo.js +433 -0
  32. data/apps/default/config/helpers/micromenus/stylesheets/carousel.css +78 -0
  33. data/apps/default/config/helpers/micromenus/stylesheets/columnav.css +135 -0
  34. data/apps/default/config/helpers/micromenus/stylesheets/microbrowsers.css +42 -0
  35. data/apps/default/config/helpers/multi_messenger.yml +5 -1
  36. data/apps/default/config/migration.rb +10 -0
  37. data/apps/default/extensions.rb +1 -1
  38. data/apps/default/helpers/factorial.alien.c +3 -3
  39. data/apps/default/helpers/lookup.rb +2 -1
  40. data/apps/default/helpers/manager_proxy.rb +67 -15
  41. data/apps/default/helpers/micromenus.rb +173 -31
  42. data/apps/default/helpers/multi_messenger.rb +20 -3
  43. data/lib/adhearsion.rb +218 -88
  44. data/lib/constants.rb +1 -0
  45. data/lib/core_extensions.rb +15 -9
  46. data/lib/phone_number.rb +85 -0
  47. data/lib/rami.rb +3 -2
  48. data/lib/servlet_container.rb +47 -24
  49. data/lib/sexy_migrations.rb +70 -0
  50. data/test/asterisk_module_test.rb +9 -9
  51. data/test/specs/numerical_string_spec.rb +53 -0
  52. metadata +31 -11
  53. data/apps/default/config/helpers/micromenus/javascripts/builder.js +0 -131
  54. data/apps/default/config/helpers/micromenus/javascripts/controls.js +0 -834
  55. data/apps/default/config/helpers/micromenus/javascripts/effects.js +0 -956
  56. data/apps/default/config/helpers/micromenus/javascripts/prototype.js +0 -2319
  57. data/apps/default/config/helpers/micromenus/javascripts/scriptaculous.js +0 -51
  58. data/apps/default/config/helpers/micromenus/javascripts/slider.js +0 -278
  59. data/apps/default/config/helpers/micromenus/javascripts/unittest.js +0 -557
  60. data/apps/default/config/helpers/micromenus/stylesheets/firefox.css +0 -10
  61. data/apps/default/config/helpers/micromenus/stylesheets/firefox.xul.css +0 -44
@@ -0,0 +1,1238 @@
1
+ /**
2
+ * Copyright (c) 2006, Bill W. Scott
3
+ * All rights reserved.
4
+ *
5
+ * This work is licensed under the Creative Commons Attribution 2.5 License. To view a copy
6
+ * of this license, visit http://creativecommons.org/licenses/by/2.5/ or send a letter to
7
+ * Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
8
+ *
9
+ * This work was created by Bill Scott (billwscott.com, looksgoodworkswell.com).
10
+ *
11
+ * The only attribution I require is to keep this notice of copyright & license
12
+ * in this original source file.
13
+ *
14
+ * Version 0.4.0 - 01.29.2007
15
+ *
16
+ */
17
+ YAHOO.namespace("extension");
18
+
19
+ /**
20
+ * @class
21
+ * The carousel class manages a content list (a set of LI elements within an UL list) that can be displayed horizontally or vertically. The content can be scrolled back and forth with or without animation. The content can reference static HTML content or the list items can be created dynamically on-the-fly (with or without Ajax). The navigation and event handling can be externalized from the class.
22
+ * @param {object|string} carouselElementID The element ID (id name or id object) of the DIV that will become a carousel
23
+ * @param {object} carouselCfg The configuration object literal containing the configuration that should be set for this module. See configuration documentation for more details.
24
+ * @constructor
25
+ */
26
+ YAHOO.extension.Carousel = function(carouselElementID, carouselCfg) {
27
+ this.init(carouselElementID, carouselCfg);
28
+ };
29
+
30
+ YAHOO.extension.Carousel.prototype = {
31
+
32
+
33
+ /**
34
+ * Constant denoting that the carousel size is unbounded (no limits set on scrolling)
35
+ * @type number
36
+ */
37
+ UNBOUNDED_SIZE: 1000000,
38
+
39
+ /**
40
+ * Initializes the carousel object and all of its local members.
41
+ * @param {object|string} carouselElementID The element ID (id name or id object)
42
+ * of the DIV that will become a carousel
43
+ * @param {object} carouselCfg The configuration object literal containing the
44
+ * configuration that should be set for this module. See configuration documentation for more details.
45
+ */
46
+ init: function(carouselElementID, carouselCfg) {
47
+
48
+ var oThis = this;
49
+
50
+ // CSS style classes
51
+ var carouselListClass = "carousel-list";
52
+ var carouselClipRegionClass = "carousel-clip-region";
53
+ var carouselNextClass = "carousel-next";
54
+ var carouselPrevClass = "carousel-prev";
55
+
56
+ this.carouselElemID = carouselElementID;
57
+ this.carouselElem = YAHOO.util.Dom.get(carouselElementID);
58
+
59
+ this.prevEnabled = true;
60
+ this.nextEnabled = true;
61
+
62
+ // Create the config object
63
+ this.cfg = new YAHOO.util.Config(this);
64
+
65
+ /**
66
+ * orientation property.
67
+ * Either "horizontal" or "vertical". Changes carousel from a
68
+ * left/right style carousel to a up/down style carousel.
69
+ */
70
+ this.cfg.addProperty("orientation", {
71
+ value:"horizontal",
72
+ handler: function(type, args, carouselElem) {
73
+ oThis.orientation = args[0];
74
+ oThis.reload();
75
+ },
76
+ validator: function(orientation) {
77
+ if(typeof orientation == "string") {
78
+ return ("horizontal,vertical".indexOf(orientation.toLowerCase()) != -1);
79
+ } else {
80
+ return false;
81
+ }
82
+ }
83
+ } );
84
+
85
+ /**
86
+ * size property.
87
+ * The upper hand for scrolling in the 'next' set of content.
88
+ * Set to a large value by default (this means unlimited scrolling.)
89
+ */
90
+ this.cfg.addProperty("size", {
91
+ value:this.UNBOUNDED_SIZE,
92
+ handler: function(type, args, carouselElem) {
93
+ oThis.size = args[0];
94
+ oThis.reload();
95
+ },
96
+ validator: oThis.cfg.checkNumber
97
+ } );
98
+
99
+ /**
100
+ * numVisible property.
101
+ * The number of items that will be visible.
102
+ */
103
+ this.cfg.addProperty("numVisible", {
104
+ value:3,
105
+ handler: function(type, args, carouselElem) {
106
+ oThis.numVisible = args[0];
107
+ oThis.load();
108
+ },
109
+ validator: oThis.cfg.checkNumber
110
+ } );
111
+
112
+ /**
113
+ * firstVisible property.
114
+ * Sets which item should be the first visible item in the carousel. Use to set which item will
115
+ * display as the first element when the carousel is first displayed. After the carousel is created,
116
+ * you can manipulate which item is the first visible by using the moveTo() or scrollTo() convenience
117
+ * methods.
118
+ */
119
+ this.cfg.addProperty("firstVisible", {
120
+ value:1,
121
+ handler: function(type, args, carouselElem) {
122
+ oThis.moveTo(args[0]);
123
+ },
124
+ validator: oThis.cfg.checkNumber
125
+ } );
126
+
127
+ /**
128
+ * scrollInc property.
129
+ * The number of items to scroll by. Think of this as the page increment.
130
+ */
131
+ this.cfg.addProperty("scrollInc", {
132
+ value:3,
133
+ handler: function(type, args, carouselElem) {
134
+ oThis.scrollInc = args[0];
135
+ },
136
+ validator: oThis.cfg.checkNumber
137
+ } );
138
+
139
+ /**
140
+ * animationSpeed property.
141
+ * The time (in seconds) it takes to complete the scroll animation.
142
+ * If set to 0, animated transitions are turned off and the new page of content is
143
+ * moved immdediately into place.
144
+ */
145
+ this.cfg.addProperty("animationSpeed", {
146
+ value:0.25,
147
+ handler: function(type, args, carouselElem) {
148
+ oThis.animationSpeed = args[0];
149
+ },
150
+ validator: oThis.cfg.checkNumber
151
+ } );
152
+
153
+ /**
154
+ * animationMethod property.
155
+ * The <a href="http://developer.yahoo.com/yui/docs/animation/YAHOO.util.Easing.html">YAHOO.util.Easing</a>
156
+ * method.
157
+ */
158
+ this.cfg.addProperty("animationMethod", {
159
+ value: YAHOO.util.Easing.easeOut,
160
+ handler: function(type, args, carouselElem) {
161
+ oThis.animationMethod = args[0];
162
+ }
163
+ } );
164
+
165
+ /**
166
+ * animationCompleteHandler property.
167
+ * JavaScript function that is called when the Carousel finishes animation
168
+ * after a next or previous nagivation.
169
+ * Only invoked if animationSpeed > 0.
170
+ * Two parameters are passed: type (set to 'onAnimationComplete') and
171
+ * args array (args[0] = direction [either: 'next' or 'previous']).
172
+ */
173
+ this.cfg.addProperty("animationCompleteHandler", {
174
+ value:null,
175
+ handler: function(type, args, carouselElem) {
176
+ if(oThis.animationCompleteEvt) {
177
+ oThis.animationCompleteEvt.unsubscribe(oThis.animationCompleteHandler, oThis);
178
+ }
179
+ oThis.animationCompleteHandler = args[0];
180
+ if(oThis._isValidObj(oThis.animationCompleteHandler)) {
181
+ oThis.animationCompleteEvt = new YAHOO.util.CustomEvent("onAnimationComplete", oThis);
182
+ oThis.animationCompleteEvt.subscribe(oThis.animationCompleteHandler, oThis);
183
+ }
184
+ }
185
+ } );
186
+
187
+ /**
188
+ * autoPlay property.
189
+ * Specifies how many milliseconds to periodically auto scroll the content.
190
+ * If set to 0 (default) then autoPlay is turned off.
191
+ * If the user interacts by clicking left or right navigation, autoPlay is turned off.
192
+ * You can restart autoPlay by calling the <em>startAutoPlay()</em>.
193
+ * If you externally control navigation (with your own event handlers)
194
+ * then you may want to turn off the autoPlay by calling<em>stopAutoPlay()</em>
195
+ */
196
+ this.cfg.addProperty("autoPlay", {
197
+ value:0,
198
+ handler: function(type, args, carouselElem) {
199
+ oThis.autoPlay = args[0];
200
+ if(oThis.autoPlay > 0)
201
+ oThis.startAutoPlay();
202
+ else
203
+ oThis.stopAutoPlay();
204
+ }
205
+ } );
206
+
207
+ /**
208
+ * wrap property.
209
+ * Specifies whether to wrap when at the end of scrolled content. When the end is reached,
210
+ * the carousel will scroll backwards to the item 1 (the animationSpeed parameter is used to
211
+ * determine how quickly it should animate back to the start.)
212
+ * Ignored if the <em>size</em> attribute is not explicitly set
213
+ * (i.e., value equals YAHOO.extension.Carousel.UNBOUNDED_SIZE)
214
+ */
215
+ this.cfg.addProperty("wrap", {
216
+ value:false,
217
+ handler: function(type, args, carouselElem) {
218
+ oThis.wrap = args[0];
219
+ },
220
+ validator: oThis.cfg.checkBoolean
221
+ } );
222
+
223
+ /**
224
+ * navMargin property.
225
+ * The margin space for the navigation controls. This is only useful for horizontal carousels
226
+ * in which you have embedded navigation controls.
227
+ * The <em>navMargin</em> allocates space between the left and right margins
228
+ * (each navMargin wide) giving space for the navigation controls.
229
+ */
230
+ this.cfg.addProperty("navMargin", {
231
+ value:0,
232
+ handler: function(type, args, carouselElem) {
233
+ oThis.navMargin = args[0];
234
+ },
235
+ validator: oThis.cfg.checkNumber
236
+ } );
237
+
238
+ // For backward compatibility. Deprecated.
239
+ this.cfg.addProperty("prevElementID", {
240
+ value: null,
241
+ handler: function(type, args, carouselElem) {
242
+ if(oThis.carouselPrev) {
243
+ YAHOO.util.Event.removeListener(oThis.carouselPrev, "click", oThis._scrollPrev);
244
+ }
245
+ oThis.prevElementID = args[0];
246
+ if(oThis.prevElementID == null) {
247
+ oThis.carouselPrev = YAHOO.util.Dom.getElementsByClassName(carouselPrevClass,
248
+ "div", oThis.carouselElem)[0];
249
+ } else {
250
+ oThis.carouselPrev = YAHOO.util.Dom.get(oThis.prevElementID);
251
+ }
252
+ YAHOO.util.Event.addListener(oThis.carouselPrev, "click", oThis._scrollPrev, oThis);
253
+ }
254
+ });
255
+
256
+ /**
257
+ * prevElement property.
258
+ * An element or elements that will provide the previous navigation control.
259
+ * prevElement may be a single element or an array of elements. The values may be strings denoting
260
+ * the ID of the element or the object itself.
261
+ * If supplied, then events are wired to this control to fire scroll events to move the carousel to
262
+ * the previous content.
263
+ * You may want to provide your own interaction for controlling the carousel. If
264
+ * so leave this unset and provide your own event handling mechanism.
265
+ */
266
+ this.cfg.addProperty("prevElement", {
267
+ value:null,
268
+ handler: function(type, args, carouselElem) {
269
+ if(oThis.carouselPrev) {
270
+ YAHOO.util.Event.removeListener(oThis.carouselPrev, "click", oThis._scrollPrev);
271
+ }
272
+ oThis.prevElementID = args[0];
273
+ if(oThis.prevElementID == null) {
274
+ oThis.carouselPrev = YAHOO.util.Dom.getElementsByClassName(carouselPrevClass,
275
+ "div", oThis.carouselElem)[0];
276
+ } else {
277
+ oThis.carouselPrev = YAHOO.util.Dom.get(oThis.prevElementID);
278
+ }
279
+ YAHOO.util.Event.addListener(oThis.carouselPrev, "click", oThis._scrollPrev, oThis);
280
+ }
281
+ } );
282
+
283
+ // For backward compatibility. Deprecated.
284
+ this.cfg.addProperty("nextElementID", {
285
+ value: null,
286
+ handler: function(type, args, carouselElem) {
287
+ if(oThis.carouselNext) {
288
+ YAHOO.util.Event.removeListener(oThis.carouselNext, "click", oThis._scrollNext);
289
+ }
290
+ oThis.nextElementID = args[0];
291
+ if(oThis.nextElementID == null) {
292
+ oThis.carouselNext = YAHOO.util.Dom.getElementsByClassName(carouselNextClass,
293
+ "div", oThis.carouselElem);
294
+ } else {
295
+ oThis.carouselNext = YAHOO.util.Dom.get(oThis.nextElementID);
296
+ }
297
+ if(oThis.carouselNext) {
298
+ YAHOO.util.Event.addListener(oThis.carouselNext, "click", oThis._scrollNext, oThis);
299
+ }
300
+ }
301
+ });
302
+
303
+ /**
304
+ * nextElement property.
305
+ * An element or elements that will provide the next navigation control.
306
+ * nextElement may be a single element or an array of elements. The values may be strings denoting
307
+ * the ID of the element or the object itself.
308
+ * If supplied, then events are wired to this control to fire scroll events to move the carousel to
309
+ * the next content.
310
+ * You may want to provide your own interaction for controlling the carousel. If
311
+ * so leave this unset and provide your own event handling mechanism.
312
+ */
313
+ this.cfg.addProperty("nextElement", {
314
+ value:null,
315
+ handler: function(type, args, carouselElem) {
316
+ if(oThis.carouselNext) {
317
+ YAHOO.util.Event.removeListener(oThis.carouselNext, "click", oThis._scrollNext);
318
+ }
319
+ oThis.nextElementID = args[0];
320
+ if(oThis.nextElementID == null) {
321
+ oThis.carouselNext = YAHOO.util.Dom.getElementsByClassName(carouselNextClass,
322
+ "div", oThis.carouselElem);
323
+ } else {
324
+ oThis.carouselNext = YAHOO.util.Dom.get(oThis.nextElementID);
325
+ }
326
+ if(oThis.carouselNext) {
327
+ YAHOO.util.Event.addListener(oThis.carouselNext, "click", oThis._scrollNext, oThis);
328
+ }
329
+ }
330
+ } );
331
+
332
+ /**
333
+ * loadInitHandler property.
334
+ * JavaScript function that is called when the Carousel needs to load
335
+ * the initial set of visible items. Two parameters are passed:
336
+ * type (set to 'onLoadInit') and an argument array (args[0] = start index, args[1] = last index).
337
+ */
338
+ this.cfg.addProperty("loadInitHandler", {
339
+ value:null,
340
+ handler: function(type, args, carouselElem) {
341
+ if(oThis.loadInitHandlerEvt) {
342
+ oThis.loadInitHandlerEvt.unsubscribe(oThis.loadInitHandler, oThis);
343
+ }
344
+ oThis.loadInitHandler = args[0];
345
+ if(oThis.loadInitHandlerEvt) {
346
+ oThis.loadInitHandlerEvt = new YAHOO.util.CustomEvent("onLoadInit", oThis);
347
+ oThis.loadInitHandlerEvt.subscribe(oThis.loadInitHandler, oThis);
348
+ }
349
+ }
350
+ } );
351
+
352
+ /**
353
+ * loadNextHandler property.
354
+ * JavaScript function that is called when the Carousel needs to load
355
+ * the next set of items (in response to the user navigating to the next set.)
356
+ * Two parameters are passed: type (set to 'onLoadNext') and
357
+ * args array (args[0] = start index, args[1] = last index).
358
+ */
359
+ this.cfg.addProperty("loadNextHandler", {
360
+ value:null,
361
+ handler: function(type, args, carouselElem) {
362
+ if(oThis.loadNextHandlerEvt) {
363
+ oThis.loadNextHandlerEvt.unsubscribe(oThis.loadNextHandler, oThis);
364
+ }
365
+ oThis.loadNextHandler = args[0];
366
+ if(oThis.loadNextHandlerEvt) {
367
+ oThis.loadNextHandlerEvt = new YAHOO.util.CustomEvent("onLoadNext", oThis);
368
+ oThis.loadNextHandlerEvt.subscribe(oThis.loadNextHandler, oThis);
369
+ }
370
+ }
371
+ } );
372
+
373
+ /**
374
+ * loadPrevHandler property.
375
+ * JavaScript function that is called when the Carousel needs to load
376
+ * the previous set of items (in response to the user navigating to the previous set.)
377
+ * Two parameters are passed: type (set to 'onLoadPrev') and args array
378
+ * (args[0] = start index, args[1] = last index).
379
+ */
380
+ this.cfg.addProperty("loadPrevHandler", {
381
+ value:null,
382
+ handler: function(type, args, carouselElem) {
383
+ if(oThis.loadPrevHandlerEvt) {
384
+ oThis.loadPrevHandlerEvt.unsubscribe(oThis.loadPrevHandler, oThis);
385
+ }
386
+ oThis.loadPrevHandler = args[0];
387
+ if(oThis.loadPrevHandlerEvt) {
388
+ oThis.loadPrevHandlerEvt = new YAHOO.util.CustomEvent("onLoadPrev", oThis);
389
+ oThis.loadPrevHandlerEvt.subscribe(oThis.loadPrevHandler, oThis);
390
+ }
391
+ }
392
+ } );
393
+
394
+ /**
395
+ * prevButtonStateHandler property.
396
+ * JavaScript function that is called when the enabled state of the
397
+ * 'previous' control is changing. The responsibility of
398
+ * this method is to enable or disable the 'previous' control.
399
+ * Two parameters are passed to this method: <em>type</em>
400
+ * (which is set to "onPrevButtonStateChange") and <em>args</em>,
401
+ * an array that contains two values.
402
+ * The parameter args[0] is a flag denoting whether the 'previous' control
403
+ * is being enabled or disabled. The parameter args[1] is the element object
404
+ * derived from the <em>prevElement</em> parameter.
405
+ * If you do not supply a prevElement then you will need to track
406
+ * the elements that you would want to enable/disable while handling the state change.
407
+ */
408
+ this.cfg.addProperty("prevButtonStateHandler", {
409
+ value:null,
410
+ handler: function(type, args, carouselElem) {
411
+ if(oThis.prevButtonStateHandler) {
412
+ oThis.prevButtonStateHandlerEvt.unsubscribe(oThis.prevButtonStateHandler, oThis);
413
+ }
414
+ oThis.prevButtonStateHandler = args[0];
415
+ if(oThis.prevButtonStateHandler) {
416
+ oThis.prevButtonStateHandlerEvt = new YAHOO.util.CustomEvent("onPrevButtonStateChange", oThis);
417
+ oThis.prevButtonStateHandlerEvt.subscribe(oThis.prevButtonStateHandler, oThis);
418
+ }
419
+ }
420
+ } );
421
+
422
+ /**
423
+ * nextButtonStateHandler property.
424
+ * JavaScript function that is called when the enabled state of the
425
+ * 'next' control is changing. The responsibility of
426
+ * this method is to enable or disable the 'next' control.
427
+ * Two parameters are passed to this method: <em>type</em>
428
+ * (which is set to "onNextButtonStateChange") and <em>args</em>,
429
+ * an array that contains two values.
430
+ * The parameter args[0] is a flag denoting whether the 'next' control
431
+ * is being enabled or disabled. The parameter args[1] is the element object
432
+ * derived from the <em>nextElement</em> parameter.
433
+ * If you do not supply a nextElement then you will need to track
434
+ * the elements that you would want to enable/disable while handling the state change.
435
+ */
436
+ this.cfg.addProperty("nextButtonStateHandler", {
437
+ value:null,
438
+ handler: function(type, args, carouselElem) {
439
+ if(oThis.nextButtonStateHandler) {
440
+ oThis.nextButtonStateHandlerEvt.unsubscribe(oThis.nextButtonStateHandler, oThis);
441
+ }
442
+ oThis.nextButtonStateHandler = args[0];
443
+ if(oThis.nextButtonStateHandler) {
444
+ oThis.nextButtonStateHandlerEvt = new YAHOO.util.CustomEvent("onNextButtonStateChange", oThis);
445
+ oThis.nextButtonStateHandlerEvt.subscribe(oThis.nextButtonStateHandler, oThis);
446
+ }
447
+ }
448
+ } );
449
+
450
+
451
+ if(carouselCfg) {
452
+ this.cfg.applyConfig(carouselCfg);
453
+ }
454
+
455
+ this.scrollInc = this.cfg.getProperty("scrollInc");
456
+ this.navMargin = this.cfg.getProperty("navMargin");
457
+ this.loadInitHandler = this.cfg.getProperty("loadInitHandler");
458
+ this.loadNextHandler = this.cfg.getProperty("loadNextHandler");
459
+ this.loadPrevHandler = this.cfg.getProperty("loadPrevHandler");
460
+ this.prevButtonStateHandler = this.cfg.getProperty("prevButtonStateHandler");
461
+ this.nextButtonStateHandler = this.cfg.getProperty("nextButtonStateHandler");
462
+ this.animationCompleteHandler = this.cfg.getProperty("animationCompleteHandler");
463
+ this.size = this.cfg.getProperty("size");
464
+ this.wrap = this.cfg.getProperty("wrap");
465
+ this.animationMethod = this.cfg.getProperty("animationMethod");
466
+ this.orientation = this.cfg.getProperty("orientation");
467
+ this.nextElementID = this.cfg.getProperty("nextElementID");
468
+ if(!this.nextElementID)
469
+ this.nextElementID = this.cfg.getProperty("nextElement");
470
+
471
+ this.prevElementID = this.cfg.getProperty("prevElementID");
472
+ if(!this.prevElementID)
473
+ this.prevElementID = this.cfg.getProperty("prevElement");
474
+
475
+ this.autoPlay = this.cfg.getProperty("autoPlay");
476
+ this.autoPlayTimer = null;
477
+ this.numVisible = this.cfg.getProperty("numVisible");
478
+ this.firstVisible = this.cfg.getProperty("firstVisible");
479
+ this.lastVisible = this.firstVisible;
480
+ this.lastPrebuiltIdx = 0;
481
+ this.currSize = 0;
482
+
483
+ // prefetch elements
484
+ this.carouselList = YAHOO.util.Dom.getElementsByClassName(carouselListClass,
485
+ "ul", this.carouselElem)[0];
486
+
487
+ if(this.nextElementID == null) {
488
+ this.carouselNext = YAHOO.util.Dom.getElementsByClassName(carouselNextClass,
489
+ "div", this.carouselElem)[0];
490
+ } else {
491
+ this.carouselNext = YAHOO.util.Dom.get(this.nextElementID);
492
+ }
493
+
494
+ if(this.prevElementID == null) {
495
+ this.carouselPrev = YAHOO.util.Dom.getElementsByClassName(carouselPrevClass,
496
+ "div", this.carouselElem)[0];
497
+ } else {
498
+ this.carouselPrev = YAHOO.util.Dom.get(this.prevElementID);
499
+ }
500
+
501
+ this.clipReg = YAHOO.util.Dom.getElementsByClassName(carouselClipRegionClass,
502
+ "div", this.carouselElem)[0];
503
+
504
+ // add a style class dynamically so that the correct styles get applied for a vertical carousel
505
+ if(this.isVertical()) {
506
+ YAHOO.util.Dom.addClass(this.carouselList, "carousel-vertical");
507
+ }
508
+
509
+ // initialize the animation objects for next/previous
510
+ this.scrollNextAnim = new YAHOO.util.Motion(this.carouselList, this.scrollNextParams,
511
+ this.cfg.getProperty("animationSpeed"), this.animationMethod);
512
+ this.scrollPrevAnim = new YAHOO.util.Motion(this.carouselList, this.scrollPrevParams,
513
+ this.cfg.getProperty("animationSpeed"), this.animationMethod);
514
+
515
+ // If they supplied a nextElementID then wire an event listener for the click
516
+ if(this.carouselNext) {
517
+ YAHOO.util.Event.addListener(this.carouselNext, "click", this._scrollNext, this);
518
+ }
519
+
520
+ // If they supplied a prevElementID then wire an event listener for the click
521
+ if(this.carouselPrev) {
522
+ YAHOO.util.Event.addListener(this.carouselPrev, "click", this._scrollPrev, this);
523
+ }
524
+
525
+ // Wire up the various event handlers that they might have supplied
526
+ if(this.loadInitHandler) {
527
+ this.loadInitHandlerEvt = new YAHOO.util.CustomEvent("onLoadInit", this);
528
+ this.loadInitHandlerEvt.subscribe(this.loadInitHandler, this);
529
+ }
530
+ if(this.loadNextHandler) {
531
+ this.loadNextHandlerEvt = new YAHOO.util.CustomEvent("onLoadNext", this);
532
+ this.loadNextHandlerEvt.subscribe(this.loadNextHandler, this);
533
+ }
534
+ if(this.loadPrevHandler) {
535
+ this.loadPrevHandlerEvt = new YAHOO.util.CustomEvent("onLoadPrev", this);
536
+ this.loadPrevHandlerEvt.subscribe(this.loadPrevHandler, this);
537
+ }
538
+ if(this.animationCompleteHandler) {
539
+ this.animationCompleteEvt = new YAHOO.util.CustomEvent("onAnimationComplete", this);
540
+ this.animationCompleteEvt.subscribe(this.animationCompleteHandler, this);
541
+ }
542
+ if(this.prevButtonStateHandler) {
543
+ this.prevButtonStateHandlerEvt = new YAHOO.util.CustomEvent("onPrevButtonStateChange",
544
+ this);
545
+ this.prevButtonStateHandlerEvt.subscribe(this.prevButtonStateHandler, this);
546
+ }
547
+ if(this.nextButtonStateHandler) {
548
+ this.nextButtonStateHandlerEvt = new YAHOO.util.CustomEvent("onNextButtonStateChange", this);
549
+ this.nextButtonStateHandlerEvt.subscribe(this.nextButtonStateHandler, this);
550
+ }
551
+
552
+ // Since loading may take some time, wire up a listener to fire when at least the first
553
+ // element actually gets loaded
554
+ YAHOO.util.Event.onAvailable(this.carouselElemID + "-item-1", this._calculateSize, this);
555
+
556
+ // Call the initial loading sequence
557
+ this._loadInitial();
558
+
559
+ },
560
+
561
+ // /////////////////// Public API //////////////////////////////////////////
562
+
563
+ /**
564
+ * Clears all items from the list and resets to the carousel to its original initial state.
565
+ */
566
+ clear: function() {
567
+ this.moveTo(1);
568
+ this._removeChildrenFromNode(this.carouselList);
569
+ this.stopAutoPlay();
570
+ this.firstVisible = 1;
571
+ this.lastVisible = 1;
572
+ this.lastPrebuiltIdx = 0;
573
+ this.currSize = 0;
574
+ this.size = this.cfg.getProperty("size");
575
+ },
576
+
577
+ /**
578
+ * Clears all items from the list and calls the loadInitHandler to load new items into the list.
579
+ * The carousel size is reset to the original size set during creation.
580
+ * @param {number} numVisible Optional parameter: numVisible.
581
+ * If set, the carousel will resize on the reload to show numVisible items.
582
+ */
583
+ reload: function(numVisible) {
584
+ // this should be deprecated, not needed since can be set via property change
585
+ if(this._isValidObj(numVisible)) {
586
+ this.numVisible = numVisible;
587
+ }
588
+ this.clear();
589
+ YAHOO.util.Event.onAvailable(this.carouselElemID + "-item-1", this._calculateSize, this);
590
+ this._loadInitial();
591
+ },
592
+
593
+ load: function() {
594
+ YAHOO.util.Event.onAvailable(this.carouselElemID + "-item-1", this._calculateSize, this);
595
+ this._loadInitial();
596
+ },
597
+
598
+ /**
599
+ * Clears all items from the list and calls the loadInitHandler to load new items into the list.
600
+ * The carousel size is reset to the original size set during creation.
601
+ * With patch from Dan Hobbs for handling unordered loading.
602
+ * @param {number} idx which item in the list to potentially create.
603
+ * If item already exists it will not create a new item.
604
+ * @param {string} innerHTML The innerHTML string to use to create the contents of an LI element.
605
+ */
606
+ addItem: function(idx, innerHTMLOrElem) {
607
+
608
+ var liElem = this.getCarouselItem(idx);
609
+
610
+ // Need to create the li
611
+ if(!this._isValidObj(liElem)) {
612
+ liElem = this._createItem(idx, innerHTMLOrElem);
613
+ this.carouselList.appendChild(liElem);
614
+
615
+ } else if(this._isValidObj(liElem.placeholder)) {
616
+ var newLiElem = this._createItem(idx, innerHTMLOrElem);
617
+ //var oldLiElem = this.carouselList.getElementsByTagName("li")[idx - 1];
618
+ this.carouselList.replaceChild(newLiElem, liElem);
619
+ }
620
+ if(this.isVertical()) {
621
+ YAHOO.util.Dom.setStyle(liElem, "height", liElem.offsetHeight + "px");
622
+ }
623
+
624
+ return liElem;
625
+
626
+ },
627
+
628
+ /**
629
+ * Inserts a new LI item before the index specified. Uses the innerHTML to create the contents of the new LI item
630
+ * @param {number} refIdx which item in the list to insert this item before.
631
+ * @param {string} innerHTML The innerHTML string to use to create the contents of an LI element.
632
+ */
633
+ insertBefore: function(refIdx, innerHTML) {
634
+ if(refIdx < 1) {
635
+ refIdx = 1;
636
+ }
637
+
638
+ var insertionIdx = refIdx - 1;
639
+
640
+ if(insertionIdx > this.lastPrebuiltIdx) {
641
+ this._prebuildItems(this.lastPrebuiltIdx, refIdx); // is this right?
642
+ }
643
+
644
+ var liElem = this._insertBeforeItem(refIdx, innerHTML);
645
+
646
+ // depends on recalculation of this.size above
647
+ if(this.firstVisible > insertionIdx || this.lastVisible < this.size) {
648
+ if(this.nextEnabled === false) {
649
+ this._enableNext();
650
+ }
651
+ }
652
+
653
+ return liElem;
654
+ },
655
+
656
+ /**
657
+ * Inserts a new LI item after the index specified. Uses the innerHTML to create the contents of the new LI item
658
+ * @param {number} refIdx which item in the list to insert this item after.
659
+ * @param {string} innerHTML The innerHTML string to use to create the contents of an LI element.
660
+ */
661
+ insertAfter: function(refIdx, innerHTML) {
662
+
663
+ if(refIdx > this.size) {
664
+ refIdx = this.size;
665
+ }
666
+
667
+ var insertionIdx = refIdx + 1;
668
+
669
+ // if we are inserting this item past where we have prebuilt items, then
670
+ // prebuild up to this point.
671
+ if(insertionIdx > this.lastPrebuiltIdx) {
672
+ this._prebuildItems(this.lastPrebuiltIdx, insertionIdx+1);
673
+ }
674
+
675
+ var liElem = this._insertAfterItem(refIdx, innerHTML);
676
+
677
+ if(insertionIdx > this.size) {
678
+ this.size = insertionIdx;
679
+ if(this.nextEnabled === false) {
680
+ this._enableNext();
681
+ }
682
+ }
683
+
684
+ // depends on recalculation of this.size above
685
+ if(this.firstVisible > insertionIdx || this.lastVisible < this.size) {
686
+ if(this.nextEnabled === false) {
687
+ this._enableNext();
688
+ }
689
+ }
690
+
691
+ return liElem;
692
+ },
693
+
694
+ /**
695
+ * Simulates a next button event. Causes the carousel to scroll the next set of content into view.
696
+ */
697
+ scrollNext: function() {
698
+ this._scrollNext(null, this);
699
+
700
+ // we know the timer has expired.
701
+ //if(this.autoPlayTimer) clearTimeout(this.autoPlayTimer);
702
+ this.autoPlayTimer = null;
703
+ if(this.autoPlay !== 0) {
704
+ this.autoPlayTimer = this.startAutoPlay();
705
+ }
706
+ },
707
+
708
+ /**
709
+ * Simulates a prev button event. Causes the carousel to scroll the previous set of content into view.
710
+ */
711
+ scrollPrev: function() {
712
+ this._scrollPrev(null, this);
713
+ },
714
+
715
+ /**
716
+ * Scrolls the content to place itemNum as the start item in the view
717
+ * (if size is specified, the last element will not scroll past the end.).
718
+ * Uses current animation speed & method.
719
+ * @param {number} newStart The item to scroll to.
720
+ */
721
+ scrollTo: function(newStart) {
722
+ this._position(newStart, true);
723
+ },
724
+
725
+ /**
726
+ * Moves the content to place itemNum as the start item in the view
727
+ * (if size is specified, the last element will not scroll past the end.)
728
+ * Ignores animation speed & method; moves directly to the item.
729
+ * Note that you can also set the <em>firstVisible</em> property upon initialization
730
+ * to get the carousel to start at a position different than 1.
731
+ * @param {number} newStart The item to move directly to.
732
+ */
733
+ moveTo: function(newStart) {
734
+ this._position(newStart, false);
735
+ },
736
+
737
+ /**
738
+ * Starts up autoplay. If autoPlay has been stopped (by calling stopAutoPlay or by user interaction),
739
+ * you can start it back up by using this method.
740
+ * @param {number} interval optional parameter that sets the interval
741
+ * for auto play the next time that autoplay fires.
742
+ */
743
+ startAutoPlay: function(interval) {
744
+ // if interval is passed as arg, then set autoPlay to this interval.
745
+ if(this._isValidObj(interval)) {
746
+ this.autoPlay = interval;
747
+ }
748
+
749
+ // if we already are playing, then do nothing.
750
+ if(this.autoPlayTimer !== null) {
751
+ return this.autoPlayTimer;
752
+ }
753
+
754
+ var oThis = this;
755
+ var autoScroll = function() { oThis.scrollNext(); };
756
+ this.autoPlayTimer = setTimeout( autoScroll, this.autoPlay );
757
+
758
+ return this.autoPlayTimer;
759
+ },
760
+
761
+ /**
762
+ * Stops autoplay. Useful for when you want to control what events will stop the autoplay feature.
763
+ * Call <em>startAutoPlay()</em> to restart autoplay.
764
+ */
765
+ stopAutoPlay: function() {
766
+ if (this.autoPlayTimer !== null) {
767
+ clearTimeout(this.autoPlayTimer);
768
+ this.autoPlayTimer = null;
769
+ }
770
+ },
771
+
772
+ /**
773
+ * Returns whether the carousel's orientation is set to vertical.
774
+ */
775
+ isVertical: function() {
776
+ return (this.orientation != "horizontal");
777
+ },
778
+
779
+
780
+ /**
781
+ * Check to see if an element (by index) has been loaded or not. If the item is simply pre-built, but not
782
+ * loaded this will return false. If the item has not been pre-built it will also return false.
783
+ * @param {number} idx Index of the element to check load status for.
784
+ */
785
+ isItemLoaded: function(idx) {
786
+ var liElem = this.getCarouselItem(idx);
787
+
788
+ // if item exists and is not a placeholder, then it is already loaded.
789
+ if(this._isValidObj(liElem) && !this._isValidObj(liElem.placeholder)) {
790
+ return true;
791
+ }
792
+
793
+ return false;
794
+ },
795
+
796
+ /**
797
+ * Lookup the element object for a carousel list item by index.
798
+ * @param {number} idx Index of the element to lookup.
799
+ */
800
+ getCarouselItem: function(idx) {
801
+ var elemName = this.carouselElemID + "-item-" + idx;
802
+ var liElem = YAHOO.util.Dom.get(elemName);
803
+ return liElem;
804
+ },
805
+
806
+ show: function() {
807
+ YAHOO.util.Dom.setStyle(this.carouselElem, "display", "block");
808
+ this.calculateSize();
809
+ },
810
+
811
+ hide: function() {
812
+ YAHOO.util.Dom.setStyle(this.carouselElem, "display", "none");
813
+ },
814
+
815
+ calculateSize: function() {
816
+ var ulKids = this.carouselList.childNodes;
817
+ var li = null;
818
+ for(var i=0; i<ulKids.length; i++) {
819
+
820
+ li = ulKids[i];
821
+ if(li.tagName == "LI" || li.tagName == "li") {
822
+ break;
823
+ }
824
+ }
825
+ var liPaddingWidth;
826
+ if(this.isVertical()) {
827
+ YAHOO.util.Dom.removeClass(this.carouselList, "carousel-horizontal");
828
+ YAHOO.util.Dom.removeClass(this.carouselList, "carousel-vertical");
829
+ YAHOO.util.Dom.addClass(this.carouselList, "carousel-vertical");
830
+ liPaddingWidth = parseInt(YAHOO.util.Dom.getStyle(li, "paddingLeft"),10) +
831
+ parseInt(YAHOO.util.Dom.getStyle(li, "paddingRight"),10) +
832
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginLeft"),10) +
833
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginRight"),10);
834
+ var liPaddingHeight = parseInt(YAHOO.util.Dom.getStyle(li, "paddingTop"),10) +
835
+ parseInt(YAHOO.util.Dom.getStyle(li, "paddingBottom"),10) +
836
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginTop"),10) +
837
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginBottom"),10);
838
+
839
+ this.scrollAmountPerInc = (li.offsetHeight+liPaddingHeight);
840
+ this.clipReg.style.width = (li.offsetWidth + liPaddingWidth) + "px";
841
+ this.clipReg.style.height = (this.scrollAmountPerInc*this.numVisible) + "px";
842
+ this.carouselElem.style.width = (li.offsetWidth + liPaddingWidth*2) + "px";
843
+
844
+ // if we set the initial start > 1 then this will adjust the scrolled location
845
+ var currY = YAHOO.util.Dom.getY(this.carouselList);
846
+ YAHOO.util.Dom.setY(this.carouselList,
847
+ currY - this.scrollAmountPerInc*(this.firstVisible-1));
848
+ } else {
849
+ YAHOO.util.Dom.removeClass(this.carouselList, "carousel-vertical");
850
+ YAHOO.util.Dom.removeClass(this.carouselList, "carousel-horizontal");
851
+ YAHOO.util.Dom.addClass(this.carouselList, "carousel-horizontal");
852
+ liPaddingWidth = parseInt(YAHOO.util.Dom.getStyle(li, "paddingLeft"),10) +
853
+ parseInt(YAHOO.util.Dom.getStyle(li, "paddingRight"),10) +
854
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginLeft"),10) +
855
+ parseInt(YAHOO.util.Dom.getStyle(li, "marginRight"),10);
856
+
857
+ this.scrollAmountPerInc = (li.offsetWidth+liPaddingWidth);
858
+ this.carouselElem.style.width = ((this.scrollAmountPerInc*this.numVisible)+this.navMargin*2) + "px";
859
+ this.clipReg.style.width = (this.scrollAmountPerInc*this.numVisible)+"px";
860
+
861
+ // if we set the initial start > 1 then this will adjust the scrolled location
862
+ var currX = YAHOO.util.Dom.getX(this.carouselList);
863
+ YAHOO.util.Dom.setX(this.carouselList,
864
+ currX - this.scrollAmountPerInc*(this.firstVisible-1));
865
+ }
866
+ },
867
+
868
+ // /////////////////// PRIVATE API //////////////////////////////////////////
869
+ _calculateSize: function(me) {
870
+ me.calculateSize();
871
+ YAHOO.util.Dom.setStyle(me.carouselElem, "visibility", "visible");
872
+ },
873
+
874
+ // From Mike Chambers: http://weblogs.macromedia.com/mesh/archives/2006/01/removing_html_e.html
875
+ _removeChildrenFromNode: function(node)
876
+ {
877
+ if(!this._isValidObj(node))
878
+ {
879
+ return;
880
+ }
881
+
882
+ var len = node.childNodes.length;
883
+
884
+ while (node.hasChildNodes())
885
+ {
886
+ node.removeChild(node.firstChild);
887
+ }
888
+ },
889
+
890
+ _prebuildLiElem: function(idx) {
891
+ var liElem = document.createElement("li");
892
+ liElem.id = this.carouselElemID + "-item-" + idx;
893
+ // this is default flag to know that we're not really loaded yet.
894
+ liElem.placeholder = true;
895
+ this.carouselList.appendChild(liElem);
896
+
897
+ this.lastPrebuiltIdx = (idx > this.lastPrebuiltIdx) ? idx : this.lastPrebuiltIdx;
898
+ },
899
+
900
+ _createItem: function(idx, innerHTMLOrElem) {
901
+ var liElem = document.createElement("li");
902
+ liElem.id = this.carouselElemID + "-item-" + idx;
903
+
904
+ // if String then assume innerHTML, else an elem object
905
+ if(typeof(innerHTMLOrElem) === "string") {
906
+ liElem.innerHTML = innerHTMLOrElem;
907
+ } else {
908
+ liElem.appendChild(innerHTMLOrElem);
909
+ }
910
+
911
+ return liElem;
912
+ },
913
+
914
+ // idx is the location to insert after
915
+ _insertAfterItem: function(refIdx, innerHTMLOrElem) {
916
+ return this._insertBeforeItem(refIdx+1, innerHTMLOrElem);
917
+ },
918
+
919
+
920
+ _insertBeforeItem: function(refIdx, innerHTMLOrElem) {
921
+
922
+ var refItem = this.getCarouselItem(refIdx);
923
+
924
+ if(this.size != this.UNBOUNDED_SIZE) {
925
+ this.size += 1;
926
+ }
927
+
928
+ for(var i=this.lastPrebuiltIdx; i>=refIdx; i--) {
929
+ var anItem = this.getCarouselItem(i);
930
+ if(this._isValidObj(anItem)) {
931
+ anItem.id = this.carouselElemID + "-item-" + (i+1);
932
+ }
933
+ }
934
+
935
+ var liElem = this._createItem(refIdx, innerHTMLOrElem);
936
+
937
+ var insertedItem = this.carouselList.insertBefore(liElem, refItem);
938
+ this.lastPrebuiltIdx += 1;
939
+
940
+ return liElem;
941
+ },
942
+
943
+ // TEST THIS... think it has to do with prebuild
944
+ insertAfterEnd: function(innerHTMLOrElem) {
945
+ return this.insertAfter(this.size, innerHTMLOrElem);
946
+ },
947
+
948
+ _position: function(newStart, showAnimation) {
949
+ // do we bypass the isAnimated check?
950
+ if(newStart > this.firstVisible) {
951
+ var inc = newStart - this.firstVisible;
952
+ this._scrollNextInc(this, inc, showAnimation);
953
+ } else {
954
+ var dec = this.firstVisible - newStart;
955
+ this._scrollPrevInc(this, dec, showAnimation);
956
+ }
957
+ },
958
+
959
+
960
+ // event handler
961
+ _scrollNext: function(e, carousel) {
962
+ if(carousel.scrollNextAnim.isAnimated()) {
963
+ return false; // might be better to set ourself waiting for animation completion and
964
+ // then just do this function. that will allow faster scroll responses.
965
+ }
966
+
967
+ // if fired by an event and wrap is set and we are already at end then wrap
968
+ var currEnd = carousel.firstVisible + carousel.numVisible-1;
969
+ if(carousel.wrap && currEnd == carousel.size) {
970
+ carousel.scrollTo(1);
971
+ } else if(e !== null) { // event fired this so disable autoplay
972
+ carousel.stopAutoPlay();
973
+ carousel._scrollNextInc(carousel, carousel.scrollInc, (carousel.cfg.getProperty("animationSpeed") !== 0));
974
+ } else {
975
+ carousel._scrollNextInc(carousel, carousel.scrollInc, (carousel.cfg.getProperty("animationSpeed") !== 0));
976
+ }
977
+
978
+
979
+ },
980
+
981
+ // probably no longer need carousel passed in, this should be correct now.
982
+ _scrollNextInc: function(carousel, inc, showAnimation) {
983
+
984
+ var currFirstVisible = carousel.firstVisible;
985
+
986
+ var newEnd = carousel.firstVisible + inc + carousel.numVisible - 1;
987
+ newEnd = (newEnd > carousel.size) ? carousel.size : newEnd;
988
+ var newStart = newEnd - carousel.numVisible + 1;
989
+ inc = newStart - carousel.firstVisible;
990
+ carousel.firstVisible = newStart;
991
+
992
+ // if the prev button is disabled and start is now past 1, then enable it
993
+ if((carousel.prevEnabled === false) && (carousel.firstVisible > 1)) {
994
+ carousel._enablePrev();
995
+ }
996
+ // if next is enabled && we are now at the end, then disable
997
+ if((carousel.nextEnabled === true) && (newEnd == carousel.size)) {
998
+ carousel._disableNext();
999
+ }
1000
+
1001
+ if(inc > 0) {
1002
+ if(carousel._isValidObj(carousel.loadNextHandler)) {
1003
+ carousel.lastVisible = carousel.firstVisible + carousel.numVisible - 1;
1004
+
1005
+ carousel.currSize = (carousel.lastVisible > carousel.currSize) ?
1006
+ carousel.lastVisible : carousel.currSize;
1007
+
1008
+ var alreadyCached = carousel._areAllItemsLoaded(currFirstVisible,
1009
+ carousel.lastVisible);
1010
+ carousel.loadNextHandlerEvt.fire(carousel.firstVisible, carousel.lastVisible, alreadyCached);
1011
+ }
1012
+
1013
+ if(showAnimation) {
1014
+ var nextParams = { points: { by: [-carousel.scrollAmountPerInc*inc, 0] } };
1015
+ if(carousel.isVertical()) {
1016
+ nextParams = { points: { by: [0, -carousel.scrollAmountPerInc*inc] } };
1017
+ }
1018
+
1019
+ carousel.scrollNextAnim = new YAHOO.util.Motion(carousel.carouselList,
1020
+ nextParams,
1021
+ carousel.cfg.getProperty("animationSpeed"), carousel.animationMethod);
1022
+ if(carousel._isValidObj(carousel.animationCompleteHandler)) {
1023
+ carousel.scrollNextAnim.onComplete.subscribe(this._handleAnimationComplete, [carousel, "next"]);
1024
+ }
1025
+ carousel.scrollNextAnim.animate();
1026
+ } else {
1027
+ if(carousel.isVertical()) {
1028
+ var currY = YAHOO.util.Dom.getY(carousel.carouselList);
1029
+
1030
+ YAHOO.util.Dom.setY(carousel.carouselList,
1031
+ currY - carousel.scrollAmountPerInc*inc);
1032
+ } else {
1033
+ var currX = YAHOO.util.Dom.getX(carousel.carouselList);
1034
+ YAHOO.util.Dom.setX(carousel.carouselList,
1035
+ currX - carousel.scrollAmountPerInc*inc);
1036
+ }
1037
+ }
1038
+
1039
+ }
1040
+
1041
+ return false;
1042
+ },
1043
+
1044
+ _handleAnimationComplete: function(type, args, argList) {
1045
+ var carousel = argList[0];
1046
+ var direction = argList[1];
1047
+
1048
+ carousel.animationCompleteEvt.fire(direction);
1049
+
1050
+
1051
+ },
1052
+
1053
+ // If EVERY item is already loaded in the range then return true
1054
+ // Also prebuild whatever is not already created.
1055
+ _areAllItemsLoaded: function(first, last) {
1056
+ var itemsLoaded = true;
1057
+ for(var i=first; i<=last; i++) {
1058
+ var liElem = this.getCarouselItem(i);
1059
+
1060
+ // If the li elem does not exist, then prebuild it in the correct order
1061
+ // but still flag as not loaded (just prebuilt the li item.
1062
+ if(!this._isValidObj(liElem)) {
1063
+ this._prebuildLiElem(i);
1064
+ itemsLoaded = false;
1065
+ // but if the item exists and is a placeholder, then
1066
+ // note that this item is not loaded (only a placeholder)
1067
+ } else if(this._isValidObj(liElem.placeholder)) {
1068
+ itemsLoaded = false;
1069
+ }
1070
+ }
1071
+ return itemsLoaded;
1072
+ },
1073
+
1074
+ _prebuildItems: function(first, last) {
1075
+ for(var i=first; i<=last; i++) {
1076
+ var liElem = this.getCarouselItem(i);
1077
+
1078
+ // If the li elem does not exist, then prebuild it in the correct order
1079
+ // but still flag as not loaded (just prebuilt the li item.
1080
+ if(!this._isValidObj(liElem)) {
1081
+ this._prebuildLiElem(i);
1082
+ }
1083
+ }
1084
+ },
1085
+
1086
+ _scrollPrev: function(e, carousel) {
1087
+ if(carousel.scrollPrevAnim.isAnimated()) {
1088
+ return false;
1089
+ }
1090
+ carousel._scrollPrevInc(carousel, carousel.scrollInc, (carousel.cfg.getProperty("animationSpeed") !== 0));
1091
+ },
1092
+
1093
+ _scrollPrevInc: function(carousel, dec, showAnimation) {
1094
+
1095
+ var currLastVisible = carousel.lastVisible;
1096
+ var newStart = carousel.firstVisible - dec;
1097
+ newStart = (newStart <= 1) ? 1 : (newStart);
1098
+ var newDec = carousel.firstVisible - newStart;
1099
+ carousel.firstVisible = newStart;
1100
+
1101
+ // if prev is enabled && we are now at position 1, then disable
1102
+ if((carousel.prevEnabled === true) && (carousel.firstVisible == 1)) {
1103
+ carousel._disablePrev();
1104
+ }
1105
+ // if the next button is disabled and end is < size, then enable it
1106
+ if((carousel.nextEnabled === false) &&
1107
+ ((carousel.firstVisible + carousel.numVisible - 1) < carousel.size)) {
1108
+ carousel._enableNext();
1109
+ }
1110
+
1111
+ // if we are decrementing
1112
+ if(newDec > 0) {
1113
+ if(carousel._isValidObj(carousel.loadPrevHandler)) {
1114
+ carousel.lastVisible = carousel.firstVisible + carousel.numVisible - 1;
1115
+
1116
+ carousel.currSize = (carousel.lastVisible > carousel.currSize) ?
1117
+ carousel.lastVisible : carousel.currSize;
1118
+
1119
+ var alreadyCached = carousel._areAllItemsLoaded(carousel.firstVisible,
1120
+ currLastVisible);
1121
+ carousel.loadPrevHandlerEvt.fire(carousel.firstVisible, carousel.lastVisible, alreadyCached);
1122
+ }
1123
+
1124
+ if(showAnimation) {
1125
+ var prevParams = { points: { by: [carousel.scrollAmountPerInc*newDec, 0] } };
1126
+ if(carousel.isVertical()) {
1127
+ prevParams = { points: { by: [0, carousel.scrollAmountPerInc*newDec] } };
1128
+ }
1129
+
1130
+ carousel.scrollPrevAnim = new YAHOO.util.Motion(carousel.carouselList,
1131
+ prevParams,
1132
+ carousel.cfg.getProperty("animationSpeed"), carousel.animationMethod);
1133
+ if(carousel._isValidObj(carousel.animationCompleteHandler)) {
1134
+ carousel.scrollPrevAnim.onComplete.subscribe(this._handleAnimationComplete, [carousel, "prev"]);
1135
+ }
1136
+ carousel.scrollPrevAnim.animate();
1137
+ } else {
1138
+ if(carousel.isVertical()) {
1139
+ var currY = YAHOO.util.Dom.getY(carousel.carouselList);
1140
+ YAHOO.util.Dom.setY(carousel.carouselList, currY +
1141
+ carousel.scrollAmountPerInc*newDec);
1142
+ } else {
1143
+ var currX = YAHOO.util.Dom.getX(carousel.carouselList);
1144
+ YAHOO.util.Dom.setX(carousel.carouselList, currX +
1145
+ carousel.scrollAmountPerInc*newDec);
1146
+ }
1147
+ }
1148
+ }
1149
+
1150
+ return false;
1151
+ },
1152
+
1153
+ /**
1154
+ * _loadInitial looks at firstItemVisible for the start (not necessarily 1)
1155
+ */
1156
+ _loadInitial: function() {
1157
+ this.lastVisible = this.firstVisible + this.numVisible - 1;
1158
+
1159
+ this.currSize = (this.lastVisible > this.currSize) ?
1160
+ this.lastVisible : this.currSize;
1161
+
1162
+ // Since firstItemVisible can be > 1 need to check for disabling either
1163
+ // previous or next controls
1164
+ if(this.firstVisible == 1) {
1165
+ this._disablePrev();
1166
+ }
1167
+ if(this.lastVisible == this.size) {
1168
+ this._disableNext();
1169
+ }
1170
+
1171
+ // Load from 1 to the last visible
1172
+ // The _calculateSize method will adjust the scroll position
1173
+ // for starts > 1
1174
+ if(this._isValidObj(this.loadInitHandler)) {
1175
+ var alreadyCached = this._areAllItemsLoaded(1, this.lastVisible);
1176
+ this.loadInitHandlerEvt.fire(1, this.lastVisible, alreadyCached);
1177
+ }
1178
+
1179
+ if(this.autoPlay !== 0) {
1180
+ this.autoPlayTimer = this.startAutoPlay();
1181
+ }
1182
+ },
1183
+
1184
+ _disablePrev: function() {
1185
+ this.prevEnabled = false;
1186
+ if(this._isValidObj(this.prevButtonStateHandlerEvt)) {
1187
+ this.prevButtonStateHandlerEvt.fire(false, this.carouselPrev);
1188
+ }
1189
+ if(this._isValidObj(this.carouselPrev)) {
1190
+ YAHOO.util.Event.removeListener(this.carouselPrev, "click", this._scrollPrev);
1191
+ }
1192
+ },
1193
+
1194
+ _enablePrev: function() {
1195
+ this.prevEnabled = true;
1196
+ if(this._isValidObj(this.prevButtonStateHandlerEvt)) {
1197
+ this.prevButtonStateHandlerEvt.fire(true, this.carouselPrev);
1198
+ }
1199
+ if(this._isValidObj(this.carouselPrev)) {
1200
+ YAHOO.util.Event.addListener(this.carouselPrev, "click", this._scrollPrev, this);
1201
+ }
1202
+ },
1203
+
1204
+ _disableNext: function() {
1205
+ if(this.wrap) {
1206
+ return;
1207
+ }
1208
+
1209
+ this.nextEnabled = false;
1210
+ if(this._isValidObj(this.nextButtonStateHandlerEvt)) {
1211
+ this.nextButtonStateHandlerEvt.fire(false, this.carouselNext);
1212
+ }
1213
+ if(this._isValidObj(this.carouselNext)) {
1214
+ YAHOO.util.Event.removeListener(this.carouselNext, "click", this._scrollNext);
1215
+ }
1216
+ },
1217
+
1218
+ _enableNext: function() {
1219
+ this.nextEnabled = true;
1220
+ if(this._isValidObj(this.nextButtonStateHandlerEvt)) {
1221
+ this.nextButtonStateHandlerEvt.fire(true, this.carouselNext);
1222
+ }
1223
+ if(this._isValidObj(this.carouselNext)) {
1224
+ YAHOO.util.Event.addListener(this.carouselNext, "click", this._scrollNext, this);
1225
+ }
1226
+ },
1227
+
1228
+ _isValidObj: function(obj) {
1229
+
1230
+ if (null == obj) {
1231
+ return false;
1232
+ }
1233
+ if ("undefined" == typeof(obj) ) {
1234
+ return false;
1235
+ }
1236
+ return true;
1237
+ }
1238
+ };