A tumblelog CMS built on AJAX, PHP and MySQL.

slimbox.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. Slimbox v1.3 - The ultimate lightweight Lightbox clone
  3. by Christophe Beyls (http://www.digitalia.be) - MIT-style license.
  4. Inspired by the original Lightbox v2 by Lokesh Dhakar.
  5. */
  6. var Lightbox = {
  7. init: function(options){
  8. this.options = Object.extend({
  9. resizeDuration: 400,
  10. resizeTransition: Fx.Transitions.sineInOut,
  11. initialWidth: 250,
  12. initialHeight: 250,
  13. animateCaption: true
  14. }, options || {});
  15. this.anchors = [];
  16. $each(document.links, function(el){
  17. if (el.rel && el.rel.test(/^lightbox/i)){
  18. el.onclick = this.click.pass(el, this);
  19. this.anchors.push(el);
  20. }
  21. }, this);
  22. this.eventKeyDown = this.keyboardListener.bindAsEventListener(this);
  23. this.eventPosition = this.position.bind(this);
  24. this.overlay = new Element('div').setProperty('id', 'lbOverlay').injectInside(document.body);
  25. 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(document.body);
  26. this.image = new Element('div').setProperty('id', 'lbImage').injectInside(this.center);
  27. this.prevLink = new Element('a').setProperties({id: 'lbPrevLink', href: '#'}).setStyle('display', 'none').injectInside(this.image);
  28. this.nextLink = this.prevLink.clone().setProperty('id', 'lbNextLink').injectInside(this.image);
  29. this.prevLink.onclick = this.previous.bind(this);
  30. this.nextLink.onclick = this.next.bind(this);
  31. this.bottomContainer = new Element('div').setProperty('id', 'lbBottomContainer').setStyle('display', 'none').injectInside(document.body);
  32. this.bottom = new Element('div').setProperty('id', 'lbBottom').injectInside(this.bottomContainer);
  33. new Element('a').setProperties({id: 'lbCloseLink', href: '#'}).injectInside(this.bottom).onclick = this.overlay.onclick = this.close.bind(this);
  34. this.caption = new Element('div').setProperty('id', 'lbCaption').injectInside(this.bottom);
  35. this.number = new Element('div').setProperty('id', 'lbNumber').injectInside(this.bottom);
  36. new Element('div').setStyle('clear', 'both').injectInside(this.bottom);
  37. var nextEffect = this.nextEffect.bind(this);
  38. this.fx = {
  39. overlay: this.overlay.effect('opacity', {duration: 500}).hide(),
  40. resize: this.center.effects({duration: this.options.resizeDuration, transition: this.options.resizeTransition, onComplete: nextEffect}),
  41. image: this.image.effect('opacity', {duration: 500, onComplete: nextEffect}),
  42. bottom: this.bottom.effect('margin-top', {duration: 400, onComplete: nextEffect})
  43. };
  44. this.preloadPrev = new Image();
  45. this.preloadNext = new Image();
  46. },
  47. click: function(link){
  48. if (link.rel.length == 8) return this.show(link.href, link.title);
  49. var j, imageNum, images = [];
  50. this.anchors.each(function(el){
  51. if (el.rel == link.rel){
  52. for (j = 0; j < images.length; j++) if(images[j][0] == el.href) break;
  53. if (j == images.length){
  54. images.push([el.href, el.title]);
  55. if (el.href == link.href) imageNum = j;
  56. }
  57. }
  58. }, this);
  59. return this.open(images, imageNum);
  60. },
  61. show: function(url, title){
  62. return this.open([[url, title]], 0);
  63. },
  64. open: function(images, imageNum){
  65. this.images = images;
  66. this.position();
  67. this.setup(true);
  68. this.top = window.getScrollTop() + (window.getHeight() / 15);
  69. this.center.setStyles({top: this.top+'px', display: ''});
  70. this.fx.overlay.start(0.8);
  71. return this.changeImage(imageNum);
  72. },
  73. position: function(){
  74. this.overlay.setStyles({top: window.getScrollTop()+'px', height: window.getHeight()+'px'});
  75. },
  76. setup: function(open){
  77. var elements = $A(document.getElementsByTagName('object'));
  78. if (window.ie) elements.extend(document.getElementsByTagName('select'));
  79. elements.each(function(el){ el.style.visibility = open ? 'hidden' : ''; });
  80. var fn = open ? 'addEvent' : 'removeEvent';
  81. window[fn]('scroll', this.eventPosition)[fn]('resize', this.eventPosition);
  82. document[fn]('keydown', this.eventKeyDown);
  83. this.step = 0;
  84. },
  85. keyboardListener: function(event){
  86. switch (event.keyCode){
  87. case 27: case 88: case 67: this.close(); break;
  88. case 37: case 80: this.previous(); break;
  89. case 39: case 78: this.next();
  90. }
  91. },
  92. previous: function(){
  93. return this.changeImage(this.activeImage-1);
  94. },
  95. next: function(){
  96. return this.changeImage(this.activeImage+1);
  97. },
  98. changeImage: function(imageNum){
  99. if (this.step || (imageNum < 0) || (imageNum >= this.images.length)) return false;
  100. this.step = 1;
  101. this.activeImage = imageNum;
  102. this.bottomContainer.style.display = this.prevLink.style.display = this.nextLink.style.display = 'none';
  103. this.fx.image.hide();
  104. this.center.className = 'lbLoading';
  105. this.preload = new Image();
  106. this.preload.onload = this.nextEffect.bind(this);
  107. this.preload.src = this.images[imageNum][0];
  108. return false;
  109. },
  110. nextEffect: function(){
  111. switch (this.step++){
  112. case 1:
  113. this.center.className = '';
  114. this.image.style.backgroundImage = 'url('+this.images[this.activeImage][0]+')';
  115. this.image.style.width = this.bottom.style.width = this.preload.width+'px';
  116. this.image.style.height = this.prevLink.style.height = this.nextLink.style.height = this.preload.height+'px';
  117. this.caption.setHTML(this.images[this.activeImage][1] || '');
  118. this.number.setHTML((this.images.length == 1) ? '' : 'Image '+(this.activeImage+1)+' of '+this.images.length);
  119. if (this.activeImage) this.preloadPrev.src = this.images[this.activeImage-1][0];
  120. if (this.activeImage != (this.images.length - 1)) this.preloadNext.src = this.images[this.activeImage+1][0];
  121. if (this.center.clientHeight != this.image.offsetHeight){
  122. this.fx.resize.start({height: this.image.offsetHeight});
  123. break;
  124. }
  125. this.step++;
  126. case 2:
  127. if (this.center.clientWidth != this.image.offsetWidth){
  128. this.fx.resize.start({width: this.image.offsetWidth, marginLeft: -this.image.offsetWidth/2});
  129. break;
  130. }
  131. this.step++;
  132. case 3:
  133. this.bottomContainer.setStyles({top: (this.top + this.center.clientHeight)+'px', height: '0px', marginLeft: this.center.style.marginLeft, display: ''});
  134. this.fx.image.start(1);
  135. break;
  136. case 4:
  137. if (this.options.animateCaption){
  138. this.fx.bottom.set(-this.bottom.offsetHeight);
  139. this.bottomContainer.style.height = '';
  140. this.fx.bottom.start(0);
  141. break;
  142. }
  143. this.bottomContainer.style.height = '';
  144. case 5:
  145. if (this.activeImage) this.prevLink.style.display = '';
  146. if (this.activeImage != (this.images.length - 1)) this.nextLink.style.display = '';
  147. this.step = 0;
  148. }
  149. },
  150. close: function(){
  151. if (this.step < 0) return;
  152. this.step = -1;
  153. if (this.preload){
  154. this.preload.onload = Class.empty;
  155. this.preload = null;
  156. }
  157. for (var f in this.fx) this.fx[f].stop();
  158. this.center.style.display = this.bottomContainer.style.display = 'none';
  159. this.fx.overlay.chain(this.setup.pass(false, this)).start(0);
  160. return false;
  161. }
  162. };
  163. window.addEvent('domready', Lightbox.init.bind(Lightbox));