more correct sizing; simplify doc structure
[mkgallery.git] / include / slideshow.js
1 \r
2 /**************************************************************\r
3 \r
4         Script          : slideShow\r
5         Version         : 1.3\r
6         Authors         : Samuel Birch\r
7         Desc            : transitions between images\r
8         Licence         : Open Source MIT Licence\r
9 \r
10 **************************************************************/\r
11 \r
12 var slideShow = new Class({\r
13         \r
14         getOptions: function(){\r
15                 return {\r
16                         effect: 'fade', //fade|wipe|slide|random\r
17                         duration: 2000,\r
18                         transition: Fx.Transitions.linear,\r
19                         direction: 'right', //top|right|bottom|left|random\r
20                         //color: false,\r
21                         wait: 5000,\r
22                         loop: true,\r
23                         thumbnails: false,\r
24                         thumbnailCls: 'outline',\r
25                         backgroundSlider: false, //change to be an instance.\r
26                         loadingCls: 'loading',\r
27                         onClick: false\r
28                 };\r
29         },\r
30 \r
31         initialize: function(container, images, options){\r
32                 this.setOptions(this.getOptions(), options);\r
33                 \r
34                 this.container = $(container);\r
35                 this.container.setStyles({\r
36                         /* position: 'relative', */\r
37                         overflow: 'hidden'\r
38                 });\r
39                 if(this.options.onClick){\r
40                         this.container.addEvent('click', function(){\r
41                                 this.options.onClick(this.imageLoaded);\r
42                         }.bind(this));\r
43                 }\r
44                 \r
45                 \r
46                 this.imagesHolder = new Element('div').setStyles({\r
47                         position: 'absolute',\r
48                         overflow: 'hidden',\r
49                         top: this.container.getStyle('height'),\r
50                         left: 0,\r
51                         width: '0px',\r
52                         height: '0px',\r
53                         display: 'none'\r
54                 }).injectInside(this.container);\r
55                 \r
56                 /*\r
57                 if($type(images) == 'string' && !this.options.thumbnails){\r
58                         var imageList = [];\r
59                         $$('.'+images).each(function(el){\r
60                                 imageList.push(el.src);\r
61                                 el.injectInside(this.imagesHolder);\r
62                         },this);\r
63                         this.images = imageList;\r
64                         \r
65                 }else if($type(images) == 'string' && this.options.thumbnails){\r
66                         var imageList = [];\r
67                         var srcList = [];\r
68                         this.thumbnails = $$('.'+images);\r
69                         this.thumbnails.each(function(el,i){\r
70                                 srcList.push(el.href);\r
71                                 imageList.push(el.getElement('img'));\r
72                                 el.href = 'javascript:;';\r
73                                 el.addEvent('click',function(){\r
74                                         this.stop();\r
75                                         this.play(i);                            \r
76                                 }.bind(this,el,i));\r
77                         },this);\r
78                         this.images = srcList;\r
79                         this.thumbnailImages = imageList;\r
80                         \r
81                         if(this.options.backgroundSlider){\r
82                                 this.bgSlider = new BackgroundSlider(this.thumbnailImages,{mouseOver: false, duration: this.options.duration, className: this.options.thumbnailCls, padding:{top:0,right:-2,bottom:-2,left:0}});\r
83                                 this.bgSlider.set(this.thumbnailImages[0]);\r
84                         }\r
85                 \r
86                 }else{\r
87                 */\r
88                         this.images = images;\r
89                 /*\r
90                 }\r
91                 */\r
92                 \r
93                 this.loading = new Element('div').addClass(this.options.loadingCls).setStyles({\r
94                         position: 'absolute',\r
95                         top: 0,\r
96                         left: 0,\r
97                         zIndex: 3,\r
98                         display: 'none',\r
99                         width: this.container.getStyle('width'),\r
100                         height: this.container.getStyle('height')\r
101                 }).injectInside(this.container);\r
102                 \r
103                 this.oldImage = new Element('div').setStyles({\r
104                         position: 'absolute',\r
105                         overflow: 'hidden',\r
106                         top: 0,\r
107                         left: 0,\r
108                         opacity: 0,\r
109                         width: this.container.getStyle('width'),\r
110                         height: this.container.getStyle('height')\r
111                 }).injectInside(this.container);\r
112                 \r
113                 this.newImage = this.oldImage.clone();\r
114                 this.newImage.injectInside(this.container);\r
115                 \r
116                 \r
117                 \r
118                 this.timer = 0;\r
119                 this.image = -1;\r
120                 this.imageLoaded = 0;\r
121                 this.stopped = true;\r
122                 this.started = false;\r
123                 this.animating = false;\r
124                 window.addEvent('resize', this.reshow.bind(this));\r
125                 window.addEvent('scroll', this.reshow.bind(this));\r
126         },\r
127         \r
128         load: function(){\r
129                 $clear(this.timer);\r
130                 this.loading.setStyle('display','block');\r
131                 this.image++;\r
132                 var i;\r
133                 var width;\r
134                 var height;\r
135                 var img;\r
136                 for (i=0;i<this.images[this.image].length;i++) {\r
137                         width = this.images[this.image][i][0];\r
138                         height = this.images[this.image][i][1];\r
139                         img = this.images[this.image][i][2];\r
140                         if (width >= this.width || height >= this.height) {\r
141                                 break;\r
142                         }\r
143                 }\r
144                 /* alert('req1 image '+img); */\r
145                 delete this.imageObj;\r
146                 \r
147                 doLoad = true;\r
148                 this.imagesHolder.getElements('img').each(function(el){\r
149                         var src = this.images[this.image][i][2];\r
150                         /* alert('req2 image '+src); */\r
151                         if(el.src == src){\r
152                                 this.imageObj = el;\r
153                                 doLoad = false;\r
154                                 this.add = false;\r
155                                 this.show();\r
156                         }\r
157                 },this);\r
158                 \r
159                 if(doLoad){\r
160                         this.add = true;\r
161                         this.imageObj = new Asset.image(img, {onload: this.show.bind(this)});\r
162                         this.imageObj.set('width', width).set('height', height);\r
163                 }\r
164                 \r
165         },\r
166 \r
167         restyle: function(imgobj){\r
168                 var width = imgobj.get('width');\r
169                 var height = imgobj.get('height');\r
170                 var vfactor = this.width/width;\r
171                 var hfactor = this.height/height;\r
172                 var factor = 1;\r
173                 if (vfactor < factor) { factor = vfactor; }\r
174                 if (hfactor < factor) { factor = hfactor; }\r
175                 factor *= .95;\r
176                 if (factor < 1) {\r
177                         height = Math.round(height * factor);\r
178                         width = Math.round(width * factor);\r
179                 }\r
180                 var topoff = (this.height - height)/2;\r
181                 var leftoff = (this.width - width)/2;\r
182                 /* alert('dim: '+width+'x'+height+'+'+leftoff+'+'+topoff); */\r
183                 imgobj.setStyles({\r
184                         position: 'absolute',\r
185                         top: topoff,\r
186                         left: leftoff,\r
187                         width: width,\r
188                         height: height,\r
189                 });\r
190         },\r
191 \r
192         show: function(add){\r
193                 \r
194                 this.restyle(this.imageObj);\r
195                 var oimg = this.oldImage.getElement('img');\r
196                 if (oimg) {\r
197                         this.restyle(oimg);\r
198                 }\r
199 \r
200                 if(this.add){\r
201                         this.imageObj.injectInside(this.imagesHolder);\r
202                 }\r
203                 \r
204                 this.newImage.setStyles({\r
205                         zIndex: 1,\r
206                         opacity: 0\r
207                 });\r
208                 var img = this.newImage.getElement('img');\r
209                 if(img){\r
210                         this.imageObj.clone().replaces(img);\r
211                         //img.replaces(this.imageObj.clone());\r
212                 }else{\r
213                         var obj = this.imageObj.clone();\r
214                         obj.injectInside(this.newImage);\r
215                 }\r
216 \r
217                 this.imageLoaded = this.image;\r
218                 this.loading.setStyle('display','none');\r
219                 this.effect();\r
220         },\r
221         \r
222         wait: function(){\r
223                 this.timer = this.load.delay(this.options.wait,this);\r
224         },\r
225         \r
226         play: function(num){\r
227                 this.position();\r
228                 if(this.stopped){\r
229                         if(num > -1){this.image = num-1};\r
230                         if(this.image < this.images.length){\r
231                                 this.stopped = false;\r
232                                 if(this.started){\r
233                                         this.next();\r
234                                 }else{\r
235                                         this.load();\r
236                                 }\r
237                                 this.started = true;\r
238                         }\r
239                 }\r
240         },\r
241         \r
242         stop: function(){\r
243                 $clear(this.timer);\r
244                 this.stopped = true;\r
245         },\r
246 \r
247         quit: function(){\r
248                 this.stop();\r
249         /* does not work */\r
250                 var oimg = this.oldImage.getElement('img');\r
251                 if (oimg) {\r
252                         oimg.dispose();\r
253                         delete oimg;\r
254                 }\r
255         },\r
256         \r
257         next: function(wait){\r
258                 var doNext = true;\r
259                 if(wait && this.stopped){\r
260                         doNext = false;\r
261                 }\r
262                 if(this.animating){\r
263                         doNext = false;\r
264                 }\r
265                 if(doNext){\r
266                         this.cloneImage();\r
267                         $clear(this.timer);\r
268                         /* console.log(this.image) */\r
269                         if(this.image < this.images.length-1){\r
270                                 if(wait){\r
271                                         this.wait();\r
272                                 }else{\r
273                                         this.load();    \r
274                                 }\r
275                         }else{\r
276                                 if(this.options.loop){\r
277                                         this.image = -1;\r
278                                         if(wait){\r
279                                                 this.wait();\r
280                                         }else{\r
281                                                 this.load();    \r
282                                         }\r
283                                 }else{\r
284                                         this.stopped = true;\r
285                                 }\r
286                         }\r
287                 }\r
288         },\r
289         \r
290         previous: function(){\r
291                 if(this.imageLoaded == 0){\r
292                         this.image = this.images.length-2;      \r
293                 }else{\r
294                         this.image = this.imageLoaded-2;\r
295                 }\r
296                 this.next();\r
297         },\r
298         \r
299         cloneImage: function(){\r
300                 var img = this.oldImage.getElement('img');\r
301                 if(img){\r
302                         this.imageObj.clone().replaces(img);\r
303                         //img.replaces(this.imageObj.clone());\r
304                 }else{\r
305                         var obj = this.imageObj.clone();\r
306                         obj.injectInside(this.oldImage);\r
307                 }\r
308                 \r
309                 this.oldImage.setStyles({\r
310                         zIndex: 0,\r
311                         top: 0,\r
312                         left: 0,\r
313                         opacity: 1\r
314                 });\r
315                 \r
316                 this.newImage.setStyles({opacity:0});\r
317         },\r
318         \r
319         \r
320         effect: function(){\r
321                 this.animating = true;\r
322                 this.effectObj = new Fx.Morph(this.newImage, {\r
323                         duration: this.options.duration,\r
324                         transition: this.options.transition\r
325                 });\r
326                 \r
327                 var myFxTypes = ['fade','wipe','slide'];\r
328                 var myFxDir = ['top','right','bottom','left'];\r
329                 \r
330                 if(this.options.effect == 'fade'){\r
331                         this.fade();\r
332                         \r
333                 }else if(this.options.effect == 'wipe'){\r
334                         if(this.options.direction == 'random'){\r
335                                 this.setup(myFxDir[Math.floor(Math.random()*(3+1))]);\r
336                         }else{\r
337                                 this.setup(this.options.direction);\r
338                         }\r
339                         this.wipe();\r
340                         \r
341                 }else if(this.options.effect == 'slide'){\r
342                         if(this.options.direction == 'random'){\r
343                                 this.setup(myFxDir[Math.floor(Math.random()*(3+1))]);\r
344                         }else{\r
345                                 this.setup(this.options.direction);\r
346                         }\r
347                         this.slide();\r
348                         \r
349                 }else if(this.options.effect == 'random'){\r
350                         var type = myFxTypes[Math.floor(Math.random()*(2+1))];\r
351                         if(type != 'fade'){\r
352                                 var dir = myFxDir[Math.floor(Math.random()*(3+1))];\r
353                                 if(this.options.direction == 'random'){\r
354                                         this.setup(dir);\r
355                                 }else{\r
356                                         this.setup(this.options.direction);\r
357                                 }\r
358                         }else{\r
359                                 this.setup();\r
360                         }\r
361                         this[type]();\r
362                 }\r
363         },\r
364         \r
365         setup: function(dir){\r
366                 if(dir == 'top'){\r
367                         this.top = -this.height;\r
368                         this.left = 0;\r
369                         this.topOut = this.height;\r
370                         this.leftOut = 0;\r
371                         \r
372                 }else if(dir == 'right'){\r
373                         this.top = 0;\r
374                         this.left = this.width;\r
375                         this.topOut = 0;\r
376                         this.leftOut = -this.width;\r
377                         \r
378                 }else if(dir == 'bottom'){\r
379                         this.top = this.height;\r
380                         this.left = 0;\r
381                         this.topOut = -this.height;\r
382                         this.leftOut = 0;\r
383                         \r
384                 }else if(dir == 'left'){\r
385                         this.top = 0;\r
386                         this.left = -this.width;\r
387                         this.topOut = 0;\r
388                         this.leftOut = this.width;\r
389                         \r
390                 }else{\r
391                         this.top = 0;\r
392                         this.left = 0;\r
393                         this.topOut = 0;\r
394                         this.leftOut = 0;\r
395                 }\r
396         },\r
397         \r
398         fade: function(){\r
399                 this.effectObj.start({\r
400                         opacity: [0,1]\r
401                 });\r
402                 this.resetAnimation.delay(this.options.duration+90,this);\r
403                 if(!this.stopped){\r
404                 this.next.delay(this.options.duration+100,this,true);\r
405                 }\r
406         },\r
407         \r
408         wipe: function(){\r
409                 this.newImage.morph({\r
410                         duration: this.options.duration,\r
411                         transition: this.options.transition,\r
412                         top: [0,this.topOut],\r
413                         left: [0, this.leftOut]\r
414                 })\r
415                 this.effectObj.start({\r
416                         top: [this.top,0],\r
417                         left: [this.left,0],\r
418                         opacity: [1,1]\r
419                 },this);\r
420                 this.resetAnimation.delay(this.options.duration+90,this);\r
421                 if(!this.stopped){\r
422                 this.next.delay(this.options.duration+100,this,true);\r
423                 }\r
424         },\r
425         \r
426         slide: function(){\r
427                 this.effectObj.start({\r
428                         top: [this.top,0],\r
429                         left: [this.left,0],\r
430                         opacity: [1,1]\r
431                 },this);\r
432                 this.resetAnimation.delay(this.options.duration+90,this);\r
433                 if(!this.stopped){\r
434                 this.next.delay(this.options.duration+100,this,true);\r
435                 }\r
436         },\r
437         \r
438         resetAnimation: function(){\r
439                 this.animating = false;\r
440         },\r
441 \r
442         position: function(){\r
443                 var myCoords = this.container.getCoordinates();\r
444                 this.width = myCoords.width;\r
445                 this.height = myCoords.height;\r
446                 /*\r
447                 this.width = this.container.getStyle('width').toInt();\r
448                 this.height = this.container.getStyle('height').toInt();\r
449                 */\r
450                 /* alert('container dim: '+this.width+'x'+this.height); */\r
451         },\r
452 \r
453         reshow: function(){\r
454                 this.position();\r
455                 this.image--;\r
456                 this.load();\r
457         },\r
458         \r
459 });\r
460 slideShow.implement(new Options);\r
461 slideShow.implement(new Events);\r
462 \r
463 \r
464 /*************************************************************/\r
465 \r