]> www.average.org Git - mkgallery.git/blob - include/lightbox.js
WIP on migratin to phatfusion slideshow
[mkgallery.git] / include / lightbox.js
1
2 /**************************************************************
3
4         Script          : Lightbox
5         Version         : 1.5
6         Authors         : Samuel Birch
7         Desc            : Extended version of Slimbox
8         Licence         : Open Source MIT Licence
9
10 **************************************************************/
11
12 var Lightbox = {
13
14         init: function(options){
15                 this.options = Object.extend({
16                         resizeDuration: 400,
17                         resizeTransition: Fx.Transitions.sineInOut,
18                         initialWidth: 250,
19                         initialHeight: 250,
20                         animateCaption: {In:true,Out:true},
21                         container: document.body,
22                         showControls: false,
23                         showNumbers: true,
24                         descriptions: false,
25                         opacity: 0.8
26                 }, options || {});
27
28                 this.anchors = [];
29                 $each(document.links, function(el){
30                         if (el.rel && el.rel.test(/^lightbox/i)){
31                                 el.onclick = this.click.pass(el, this);
32                                 this.anchors.push(el);
33                         }
34                 }, this);
35                 this.eventKeyDown = this.keyboardListener.bindAsEventListener(this);
36                 this.eventPosition = this.position.bind(this);
37
38                 this.overlay = new Element('div').setProperty('id', 'lbOverlay').injectInside(this.options.container);
39
40                 this.center = new Element('div').setProperty('id', 'lbCenter').setStyles({width: this.options.initialWidth+'px', height: this.options.initialHeight+'px', marginLeft: '-'+(this.options.initialWidth/2)+'px', display: 'none'}).injectInside(this.options.container);
41                 this.image = new Element('div').setProperty('id', 'lbImage').injectInside(this.center);
42                 
43                 this.bottomContainer = new Element('div').setProperty('id', 'lbBottomContainer').setStyle('display', 'none').injectInside(this.options.container);
44                 this.bottom = new Element('div').setProperty('id', 'lbBottom').injectInside(this.bottomContainer);
45                 
46                 if(this.options.showControls){
47                         this.controlDiv = new Element('div').setProperty('id','lbControls').injectInside(this.bottom);
48                 }else{
49                         this.controlDiv = this.image;
50                 }
51                 this.prevLink = new Element('a').setProperties({id: 'lbPrevLink', href: '#'}).setStyle('display', 'none').injectInside(this.controlDiv);
52                 this.nextLink = this.prevLink.clone().setProperty('id', 'lbNextLink').injectInside(this.controlDiv);
53                 this.prevLink.onclick = this.previous.bind(this);
54                 this.nextLink.onclick = this.next.bind(this);
55
56                 this.closeButton = new Element('a').setProperties({id: 'lbCloseLink', href: '#'}).injectInside(this.bottom)
57                 this.closeButton.onclick = this.overlay.onclick = this.close.bind(this);
58                 
59                 this.caption = new Element('div').setProperty('id', 'lbCaption').injectInside(this.bottom);
60                 if(this.options.descriptions != false){
61                         this.options.descriptions = $$(this.options.descriptions);
62                         this.description = new Element('div').setProperty('id', 'lbDescription').injectInside(this.bottom);
63                 }
64                 if(this.options.showNumbers){
65                         this.number = new Element('div').setProperty('id', 'lbNumber').injectInside(this.bottom);
66                 }
67                 new Element('div').setStyle('clear', 'both').injectInside(this.bottom);
68
69                 var nextEffect = this.nextEffect.bind(this);
70                 this.fx = {
71                         overlay: this.overlay.effect('opacity', {duration: 500}).hide(),
72                         resize: this.center.effects({duration: this.options.resizeDuration, transition: this.options.resizeTransition, onComplete: nextEffect}),
73                         image: this.image.effect('opacity', {duration: 500, onComplete: nextEffect}),
74                         bottom: this.bottom.effect('margin-top', {duration: 400, onComplete: nextEffect})
75                 };
76
77                 this.preloadPrev = new Image();
78                 this.preloadNext = new Image();
79         },
80
81         click: function(link){
82         
83                 this.options.descriptions.each(function(el,i){
84                         if(el.hasClass(link.id)){
85                                 this.linkLoc = i;
86                         }
87                 },this);
88                                 
89                 if (link.rel.length == 8) return this.show(link.href, link.title);
90
91                 var j, imageNum, images = [];
92                 this.anchors.each(function(el){
93                         if (el.rel == link.rel){
94                                 for (j = 0; j < images.length; j++) if(images[j][0] == el.href) break;
95                                 if (j == images.length){
96                                         images.push([el.href, el.title]);
97                                         if (el.href == link.href) imageNum = j;
98                                 }
99                         }
100                 }, this);
101                 return this.open(images, imageNum);
102         },
103
104         show: function(url, title){
105                 return this.open([[url, title]], 0);
106         },
107
108         open: function(images, imageNum){
109                 this.images = images;
110                 this.position();
111                 this.setup(true);
112                 this.top = window.getScrollTop() + (window.getHeight() / 15);
113                 this.window = {};
114                 this.window.height = window.getScrollHeight();
115                 this.window.width = window.getScrollWidth();
116                 this.window.top = window.getScrollTop();
117                 this.window.left = window.getScrollLeft();
118                 this.center.setStyles({top: this.top+'px', display: ''});
119                 this.fx.overlay.start(this.options.opacity);
120                 return this.changeImage(imageNum);
121         },
122
123         position: function(){ 
124                 if(this.options.container == document.body){ 
125                         var h = window.getScrollHeight()+'px'; 
126                         var w = window.getScrollWidth()+'px';
127                         this.overlay.setStyles({top: '0px', height: h, width: w}); 
128                 }else{ 
129                         var myCoords = this.options.container.getCoordinates(); 
130                         this.overlay.setStyles({
131                                 top: myCoords.top+'px', 
132                                 height: myCoords.height+'px', 
133                                 left: myCoords.left+'px', 
134                                 width: myCoords.width+'px'
135                         }); 
136                 } 
137         },
138
139         setup: function(open){
140                 var elements = $A(document.getElementsByTagName('object'));
141                 if (window.ie) elements.extend(document.getElementsByTagName('select'));
142                 elements.each(function(el){ el.style.visibility = open ? 'hidden' : ''; });
143                 var fn = open ? 'addEvent' : 'removeEvent';
144                 window[fn]('scroll', this.eventPosition)[fn]('resize', this.eventPosition);
145                 document[fn]('keydown', this.eventKeyDown);
146                 this.step = 0;
147         },
148
149         keyboardListener: function(event){
150                 switch (event.keyCode){
151                         case 27: case 88: case 67: this.close(); break;
152                         case 37: case 80: this.previous(); break;       
153                         case 39: case 78: this.next();
154                 }
155         },
156
157         previous: function(){
158                 this.linkLoc --;
159                 return this.changeImage(this.activeImage-1);
160         },
161
162         next: function(){
163                 this.linkLoc ++;
164                 return this.changeImage(this.activeImage+1);
165         },
166
167         changeImage: function(imageNum){
168                 if (this.step || (imageNum < 0) || (imageNum >= this.images.length)) return false;
169                 this.step = 1;
170                 this.activeImage = imageNum;
171                 if(this.options.animateCaption.In && this.bottom.offsetHeight){
172                         this.prevLink.style.display = this.nextLink.style.display = 'none';
173                         this.bottom.effect('margin-top', {duration: 300, onComplete: this.loadImage.bind(this)}).start(-this.bottom.offsetHeight);
174                 }else{
175                         this.bottomContainer.style.display = this.prevLink.style.display = this.nextLink.style.display = 'none';
176                         this.loadImage();
177                 }
178                 this.fx.image.hide();
179                 this.center.className = 'lbLoading';
180                 
181                 return false;
182         },
183         
184         loadImage: function(){
185                 this.preload = new Image();
186                 this.preload.onload = this.nextEffect.bind(this);
187                 this.preload.src = this.images[this.activeImage][0];
188         },
189
190         nextEffect: function(){
191                 switch (this.step++){
192                 case 1:
193                         this.center.className = '';
194                         this.image.style.backgroundImage = 'url('+this.images[this.activeImage][0]+')';
195                         this.image.style.width = this.bottom.style.width = this.preload.width+'px';
196                         if(this.options.showControls){
197                                 this.image.style.height = this.preload.height+'px';
198                         }else{
199                                 this.image.style.height = this.prevLink.style.height = this.nextLink.style.height = this.preload.height+'px';
200                         }
201
202                         this.caption.setHTML(this.images[this.activeImage][1] || '');
203                         if(this.options.descriptions != false){
204                                 if(this.description.getFirst()){this.description.getFirst().remove()};
205                                 var cl = this.options.descriptions[this.linkLoc].clone();
206                                 cl.setStyle('display', 'block').injectInside(this.description);
207                         }
208                         if(this.options.showNumbers){
209                                 this.number.setHTML((this.images.length == 1) ? '' : 'Image '+(this.activeImage+1)+' of '+this.images.length);
210                         }
211
212                         if (this.activeImage) this.preloadPrev.src = this.images[this.activeImage-1][0];
213                         if (this.activeImage != (this.images.length - 1)) this.preloadNext.src = this.images[this.activeImage+1][0];
214                         if (this.center.clientHeight != this.image.offsetHeight){
215                                 this.fx.resize.start({height: this.image.offsetHeight});
216                                 break;
217                         }
218                         this.step++;
219                 case 2:
220                         if (this.center.clientWidth != this.image.offsetWidth){
221                                 this.fx.resize.start({width: this.image.offsetWidth, marginLeft: -this.image.offsetWidth/2});
222                                 break;
223                         }
224                         this.step++;
225                 case 3:
226                         this.bottomContainer.setStyles({top: (this.top + this.center.clientHeight)+'px', height: '0px', marginLeft: this.center.style.marginLeft, display: ''});
227                         this.fx.image.start(1);
228                         var extra = this.caption.getStyle('height').toInt();
229                         if(this.options.descriptions != false){extra += this.description.getStyle('height').toInt()}
230                         if(this.options.showControls){extra += this.controlDiv.getStyle('height').toInt()}
231                         if(this.options.showNumbers){extra += this.number.getStyle('height').toInt()}
232                         var num = (extra-(this.closeButton.getStyle('height').toInt()*2));
233                         if(num < 0){num=0}
234                         this.closeButton.setStyle('marginTop', num+'px');
235                         if(this.activeImage != 0) this.prevLink.style.display = '';
236                         if(this.activeImage != (this.images.length - 1)) this.nextLink.style.display = '';
237                         break;
238                 case 4:
239                         if (this.options.animateCaption.Out){
240                                 this.fx.bottom.set(-this.bottom.offsetHeight);
241                                 this.bottomContainer.style.height = '';
242                                 this.fx.bottom.start(0);
243                                 break;
244                         }
245                         this.bottomContainer.style.height = '';
246                 case 5:
247                         this.step = 0;
248                 }
249         },
250
251         close: function(){
252                 if (this.step < 0) return;
253                 this.step = -1;
254                 if (this.preload){
255                         this.preload.onload = Class.empty;
256                         this.preload = null;
257                 }
258                 for (var f in this.fx) this.fx[f].stop();
259                 this.center.style.display = this.bottomContainer.style.display = 'none';
260                 this.fx.overlay.chain(this.setup.pass(false, this)).start(0);
261                 this.overlay.setStyles({height: this.window.height+'px', width: this.window.width+'px'});
262                 return false;
263         }
264
265 };
266
267 /*************************************************************/
268