/* sw.scriptaculous.gallery Author: Sven Wappler (http://www.wappler.eu) Version: 0.8 This gallery script is based on JonDesign's SmoothGallery, but this works with prototype and scriptaculous Copyright (C) 2007 Sven Wappler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ Function.prototype.create = function(options) { var fn = this; options = $H({ 'bind': fn, 'event': false, 'arguments': null, 'delay': false, 'periodical': false, 'attempt': false }).merge(options); if (options.get('arguments') != null && typeof options.get('arguments') != 'undefined' && !(options.get('arguments') instanceof Array)) options.set('arguments',[options.get('arguments')]); /* not sure */ return function(event){ var args = options.get('arguments') || arguments; if (options.get('event')){ event = (options.get('event') === true) ? event || window.event : new options.event(event); args = [event].concat(args); } var returns = function(){ return fn.apply(options.get('bind'), args); }; if (options.get('delay')) return setTimeout(returns, options.get('delay')); if (options.get('periodical')) return setInterval(returns, options.get('periodical')); if (options.get('attempt')){ try { var result = returns(); } catch(err){ result = err; } finally { return result; } } else return returns(); } } Function.prototype.delay = function(ms, bind, args) { return this.create({'delay': ms, 'bind': bind, 'arguments': args})(); } var Scroller = Class.create(); Scroller.prototype = { initialize : function(owner,wrapper) { this.owner = owner; this.wrapper = wrapper; this.direction = 0; this.running = false; this.mousex = 0; this.mousey = 0; this.position = 0; this.element = this.wrapper.childNodes[0]; this.speed = 0.006; this.timeoutdelay = 40; Event.observe(document,'mousemove', this.mousemove.bindAsEventListener(this)); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); }, mousemove : function(e) { this.mousex = Event.pointerX(e); this.mousey = Event.pointerY(e); }, start : function() { this.running = true; this.run(); }, stop : function() { this.running = false; }, moveLeft : function() { this.direction = 1; }, moveRight : function() { this.direction = -1; }, run : function() { var p = this.mousex-Position.cumulativeOffset(this.wrapper)[0]; var p1 = p/Element.getDimensions(this.wrapper).width; var p = this.mousey-Position.cumulativeOffset(this.wrapper)[1]; var p2 = p/(Element.getDimensions(this.wrapper).height+20); if (p2 > 1.4 && this.owner.carouselContainer.style.top === "0px") { this.owner.toggleCarousel(); this.stop(); } if (p1 > 0.8 && this.position <= 1-this.speed && p2 >= 0 && p2 <= 1) { this.position += this.speed; } else if (p1 < 0.2 && this.position >= this.speed && p2 >= 0 && p2 <= 1) { this.position -= this.speed; } else { } this.position = Math.round(this.position*100)/100; Element.setStyle(this.element,{ left: Math.round((Element.getDimensions(this.element).width - Element.getDimensions(this.wrapper).width ) * -this.position + this.originalLeft) + 'px' }); if (!this.running) return; setTimeout(function(){ this.run() }.bind(this) , this.timeoutdelay); } } var Gallery = Class.create(); Gallery.prototype = { initialize: function(element, options) { this.options = $H({ showArrows: true, showCarousel: false, showInfopane: false, thumbHeight: 75, thumbWidth: 100, thumbSpacing: 10, embedLinks: false, fadeDuration: 0.5, timed: true, delay: 5000, preloader: true, manualData: [], populateData: true, elementSelector: "div.imageElement", titleSelector: "h3", subtitleSelector: "p", linkSelector: "a.open", imageSelector: "img.full", thumbnailSelector: "img.thumbnail", slideInfoZoneOpacity: 0.7, carouselMinimizedOpacity: 0.4, carouselMinimizedHeight: 20, carouselMaximizedOpacity: 0.7, destroyAfterPopulate: true, baseClass: 'swGallery', withArrowsClass: 'withArrows', useThumbGenerator: false, thumbGenerator: 'resizer.php', lang : 'en' }).merge(options); this.msg_opener = $H({ 'fr' : 'Images', 'en' : 'Overview', 'sp' : 'Resumen', 'it' : 'Pictures', 'de' : 'Übersicht' }); this.currentIter = 0; this.lastIter = 0; this.maxIter = 0; this.galleryElement = element; this.galleryData = this.options.get('manualData'); this.galleryInit = 1; this.galleryElements = Array(); this.thumbnailElements = Array(); Element.addClassName(this.galleryElement,this.options.get('baseClass')); if (this.options.get('populateData')) this.populateData(); element.style.display="block"; if (this.options.get('embedLinks')) { this.currentLink = Builder.node('a', { className : 'open' , href: '#' , title: '' }); element.appendChild(this.currentLink); if ((!this.options.get('showArrows')) && (!this.options.get('showCarousel'))) this.galleryElement = element = this.currentLink; else Element.setStyle(this.currentLink,{'display' : 'none'}); } this.constructElements(); if ((data.length>1) && (this.options.get('showArrows'))) { var leftArrow = Builder.node('a',{className : 'left' }); element.appendChild(leftArrow); Event.observe(leftArrow,'click', this.prevItem.bindAsEventListener(this), false); var rightArrow = Builder.node('a',{className : 'right' }); element.appendChild(rightArrow); Event.observe(rightArrow,'click', this.nextItem.bindAsEventListener(this), false); Element.addClassName(this.galleryElement,this.options.get('withArrowsClass')); } this.loadingElement = Builder.node('div',{className : 'loadingElement' }); element.appendChild(this.loadingElement); if (this.options.get('showInfopane')) this.initInfoSlideshow(); if (this.options.get('showCarousel')) this.initCarousel(); this.doSlideShow(1); }, populateData: function() { currentArrayPlace = this.galleryData.length; options = this.options; data = this.galleryData; this.galleryElement.getElementsBySelector(options.get('elementSelector')).each(function(el) { elementDict = { image: (el.getElementsBySelector(options.get('imageSelector'))[0]).getAttribute('src'), number: currentArrayPlace }; if ((options.get('showInfopane')) | (options.get('showCarousel'))) Object.extend(elementDict, { title: el.getElementsBySelector(options.get('titleSelector'))[0].innerHTML, description: el.getElementsBySelector(options.get('subtitleSelector'))[0].innerHTML }); if (options.get('embedLinks')) Object.extend(elementDict, { link: el.getElementsBySelector(options.get('linkSelector'))[0].href||false, linkTitle: el.getElementsBySelector(options.get('linkSelector'))[0].title||false }); if ((!options.get('useThumbGenerator')) && (options.get('showCarousel'))) Object.extend(elementDict, { thumbnail: el.getElementsBySelector(options.get('thumbnailSelector'))[0].src }); else if (options.get('useThumbGenerator')) Object.extend(elementDict, { thumbnail: options.get('thumbGenerator')+'?imgfile=' + elementDict.image + '&max_width=' + options.get('thumbWidth') + '&max_height=' + options.get('thumbHeight') }); data[currentArrayPlace] = elementDict; currentArrayPlace++; if (this.options.get('destroyAfterPopulate')) el.remove(); }); this.galleryData = data; }, constructElements: function() { el = this.galleryElement; this.maxIter = this.galleryData.length; var currentImg; for(i=0;i= this.maxIter) this.nextIter = 0; this.galleryInit = 0; this.goTo(this.nextIter); }, prevItem: function() { this.nextIter = this.currentIter-1; if (this.nextIter <= -1) this.nextIter = this.maxIter - 1; this.galleryInit = 0; this.goTo(this.nextIter); }, changeItem: function(num) { this.galleryInit = 0; if (this.currentIter != num) { for(i=0;i this.currentIter) { new Effect.Opacity(this.galleryElements[num], {duration: this.options.get('fadeDuration'), from:0, to: 1}); } else { Element.setStyle( this.galleryElements[num] ,{'opacity' : 100}); new Effect.Opacity(this.galleryElements[this.currentIter], {duration: this.options.get('fadeDuration'), from:1, to: 0}); } this.currentIter = num; } this.doSlideShow.bind(this)(); }, clearTimer: function() { if (this.options.get('timed')) clearTimeout(this.timer); }, prepareTimer: function() { if (this.options.get('timed')) this.timer = this.nextItem.delay(this.options.get('delay'), this); }, doSlideShow: function(position) { if (this.galleryInit == 1) { imgPreloader = new Image(); imgPreloader.onload=function(){ this.startSlideShow(); }.bind(this); imgPreloader.src = this.galleryData[0].image; } else { if (this.options.get('showInfopane')) { this.showInfoSlideShow.delay((500 + this.options.get('fadeDuration')), this); } } }, initCarousel: function () { this.carouselContainer = Builder.node('div', {id : 'carouselContainer', className : 'carouselContainer'}); //Element.setStyle(this.carouselContainer,{'opacity' : this.options.carouselMinimizedOpacity}); this.galleryElement.appendChild(this.carouselContainer); this.carouselContainer.normalHeight = this.carouselContainer.offsetHeight; Element.setStyle(this.carouselContainer,{'top': (this.options.get('carouselMinimizedHeight') - this.carouselContainer.normalHeight)}); this.carouselBtn = Builder.node('a', {className : 'carouselBtn', title: this.msg_opener.get([this.options.get('lang')])}); this.carouselBtn.innerHTML = this.msg_opener.get([this.options.get('lang')]); this.carouselContainer.appendChild(this.carouselBtn); Event.observe(this.carouselBtn,'click', function () { this.toggleCarousel(); }.bindAsEventListener(this), false); this.carouselActive = false; this.carousel = Builder.node('div', { className : 'carousel' } ); this.carouselContainer.appendChild(this.carousel); this.carouselInner = Builder.node('div', { className : 'carouselInner' }); this.carouselWrapper = Builder.node('div', { className : 'carouselWrapper' }, [ this.carouselInner ] ); this.carouselLabel = Builder.node('p', { className : 'label' }); this.carousel.appendChild(this.carouselLabel ); this.carousel.appendChild(this.carouselWrapper ); Element.setStyle(this.carouselContainer.id,{'top' : '-'+Element.getDimensions(this.carousel).height+'px'}); Element.setStyle(this.carouselInner,{'overflow' : "hidden", "position" : "absolute"}); this.scroller = new Scroller(this,this.carouselWrapper); this.constructThumbnails(); this.carouselInner.style.width = ((this.maxIter * (this.options.get('thumbWidth') + this.options.get('thumbSpacing'))) - this.options.get('thumbSpacing') + this.options.get('thumbWidth')) + "px"; }, toggleCarousel: function() { if (this.carouselActive) this.hideCarousel(); else this.showCarousel(); }, showCarousel: function () { new Effect.Move(this.carouselContainer,{ x: 0, y: this.carousel.getDimensions().height, mode: 'relative'}); this.carouselActive = true; this.scroller.start(); }, hideCarousel: function () { new Effect.Move(this.carouselContainer,{ x: 0, y: -this.carousel.getDimensions().height, mode: 'relative'}); this.carouselActive = false; this.scroller.stop(); }, thumbnailMousOver : function(e,thumbnail) { this.carouselLabel.innerHTML = '' + (thumbnail.relatedImage.number + 1) + "/" + this.maxIter + ": " + thumbnail.relatedImage.title; new Effect.Opacity(thumbnail.id, {duration:0.5, from: this.options.get('carouselMinimizedOpacity'), to:1.0}); }, thumbnailMousOut : function(e,thumbnail) { this.carouselLabel.innerHTML = ''; new Effect.Opacity(thumbnail.id, {duration:0.5, from: 1.0, to: this.options.get('carouselMinimizedOpacity')}); }, thumbnailClick : function(e,thumbnail) { this.goTo(thumbnail.relatedImage.number); }, constructThumbnails: function () { for(i=0;i