// Slidalicious - Slideshow, v. 0.5.0 // Copyright (c) 2006 Flurin Egger, DigitPaint B.V. (http://www.digitpaint.nl) // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -- // (Lightweight) Prototype JavaScript framework, version 1.4.0_rc2 // (c) 2005 Sam Stephenson // Prototype is freely distributable under the terms of an MIT-style license. // Modified and lightweighted for specific use with Slidalicious // Modifications by Flurin Egger, DigitPaint B.V. (http://www.digitpaint.nl) // -- // Scriptacolous, version 1.5_rc3 // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Scriptacolous is freely distributable under the terms of an MIT-style license. // The following classes are part of the Script.aculo.us library: // Effect.Base, Effect.Appear, Effect.Opacity // These classes were modified and lightweighted to reduce code-footprint and // tailor them to the use within Slidalicious. They can however be replaced with // the original libraries. // ----- function $(element) { if (typeof element == 'string') element = document.getElementById(element); return element; } // -------------------------------- // var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } } Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; } Function.prototype.bind = function(object) { var __method = this; return function() { return __method.apply(object, arguments); } } // -------------------------------------- // Element = new Object(); Object.extend(Element,{ // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node); } }, show: function(el) { $(el).style.display = ''; }, hide: function(el) { $(el).style.display = 'none'; }, getDimensions: function(element) { element = $(element); if (Element.getStyle(element, 'display') != 'none') return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; els.visibility = 'hidden'; els.position = 'absolute'; els.display = ''; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = 'none'; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; if (window.opera) { element.style.top = 0; element.style.left = 0; } } }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } }, makeClipping: function(element) { element = $(element); if (element._overflow) return; element._overflow = element.style.overflow; if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden'; }, undoClipping: function(element) { element = $(element); if (element._overflow) return; element.style.overflow = element._overflow; element._overflow = undefined; }, getStyle: function(element,style){ element = $(element); var value = element.style[style]; if (!value) { if (document.defaultView && document.defaultView.getComputedStyle) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css.getPropertyValue(style) : null; } else if (element.currentStyle) { value = element.currentStyle[style]; } } if (window.opera && (style == 'left' || style == 'top' || style == 'right' || style == 'bottom')) if (Element.getStyle(element, 'position') == 'static') value = 'auto'; return value == 'auto' ? null : value; }, setStyle: function(element, style) { element = $(element); for(k in style) element.style[k] = style[k]; }, getOpacity: function(element){ var opacity; if (opacity = Element.getStyle(element, 'opacity')) return parseFloat(opacity); if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) if(opacity[1]) return parseFloat(opacity[1]) / 100; return 1.0; }, setOpacity: function(element, value){ element= $(element); if (value == 1){ Element.setStyle(element, { opacity: (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : null }); if(/MSIE/.test(navigator.userAgent)) Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); } else { if(value < 0.00001) value = 0; Element.setStyle(element, {opacity: value}); if(/MSIE/.test(navigator.userAgent)) Element.setStyle(element, { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 'alpha(opacity='+value*100+')' }); } } }); // ================================ // var Effect = new Object(); Effect.Base = Class.create(); Effect.Base.prototype = { position: null, setOptions: function(options) { this.options = Object.extend({ transition: function(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5;}, duration: 1.0, // seconds fps: 25.0, // max. 25fps due to Effect.Queue implementation from: 0.0, to: 1.0 }, options || {}); }, start: function(options) { this.setOptions(options || {}); this.currentFrame = 0; this.state = 'idle'; this.startOn = new Date().getTime(); this.finishOn = this.startOn + (this.options.duration*1000); this.event('beforeStart'); if(!this.interval) this.interval = setInterval(this.startLoop.bind(this), 40); }, startLoop: function(){ var timePos = new Date().getTime(); this.loop(timePos); }, loop: function(timePos) { if(timePos >= this.startOn) { if(timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if(this.finish) this.finish(); this.event('afterFinish'); return; } var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); var frame = Math.round(pos * this.options.fps * this.options.duration); if(frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, render: function(pos) { if(this.state == 'idle') { this.state = 'running'; this.event('beforeSetup'); if(this.setup) this.setup(); this.event('afterSetup'); } if(this.state == 'running') { if(this.options.transition) pos = this.options.transition(pos); pos *= (this.options.to-this.options.from); pos += this.options.from; this.position = pos; this.event('beforeUpdate'); if(this.update) this.update(pos); this.event('afterUpdate'); } }, cancel: function() { clearInterval(this.interval); this.interval = null; this.state = 'finished'; }, event: function(eventName) { if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if(this.options[eventName]) this.options[eventName](this); } } // ---------- core effects ------------ // Effect.Opacity = Class.create(); Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); // make this work on IE on elements without 'layout' if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) Element.setStyle(this.element, {zoom: 1}); var options = Object.extend({ from: Element.getOpacity(this.element) || 0.0, to: 1.0 }, arguments[1] || {}); this.start(options); }, update: function(position) { Element.setOpacity(this.element, position); } }); Effect.Slide = Class.create(); Object.extend(Object.extend(Effect.Slide.prototype, Effect.Base.prototype), { initialize: function(element, percent) { this.element = $(element) Element.cleanWhitespace(this.element); var options = Object.extend({ slideX: true, slideY: true, slideFrom: 100.0, slideTo: percent }, arguments[2] || {}); this.start(options); }, setup: function() { this.factor = (this.options.slideTo - this.options.slideFrom)/100; this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if(this.dims[0] == 0 && this.dims[1] == 0){ var e = Element.getDimensions(this.element); this.dims = [e.height,e.width]; } Element.makePositioned(this.element); Element.makePositioned(this.element.firstChild); if(window.opera) Element.setStyle(this.element, {top: ''}); Element.makeClipping(this.element); var direction = -1; if(this.options.slideFrom > this.options.slideTo) direction = 1; this.orig_x = direction * this.dims[1]; this.orig_y = direction * this.dims[0]; var d = {}; if(this.options.slideX) d.left = this.orig_x + "px"; if(this.options.slideY) d.top = this.orig_y + "px"; Element.setStyle(this.element.firstChild,d); Element.show(this.element); }, finish: function(){ Element.undoClipping(this.element); Element.undoPositioned(this.element.firstChild); Element.undoPositioned(this.element); }, update: function(position) { var currentScale = (this.options.slideFrom/100.0) + (this.factor * position); if(this.options.slideFrom > this.options.slideTo){ this.setPosition(this.dims[0] * currentScale, this.dims[1] * currentScale); } else { this.setPosition(this.orig_y + (this.dims[0] * currentScale), this.orig_x + (this.dims[1] * currentScale)); } }, setPosition: function(top, left) { var d = {}; if(this.options.slideX) d.left = left + 'px'; if(this.options.slideY) d.top = top + 'px'; Element.setStyle(this.element.firstChild, d); } }); // -------------------------------- // Effect.Appear = function(element) { return new Effect.Opacity(element, Object.extend({ from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0), to: 1.0, beforeSetup: function(effect) { Element.setOpacity(effect.element, effect.options.from); Element.show(effect.element); } }, arguments[1] || {})); } Effect.SlideDown = function(element) { return new Effect.Slide(element, 100, Object.extend({ slideX: false, slideFrom: 0 }, arguments[1] || {}) ); } Effect.SlideUp = function(element) { return new Effect.Slide(element, 0, Object.extend({ slideX: false, slideFrom: 100 }, arguments[1] || {}) ); } Effect.SlideLeft = function(element) { return new Effect.Slide(element, 0, Object.extend({ slideY: false, slideFrom: 100 }, arguments[1] || {}) ); } Effect.SlideRight = function(element) { return new Effect.Slide(element, 100, Object.extend({ slideY: false, slideFrom: 0 }, arguments[1] || {}) ); } // ======================================= // var Slidalicious = Class.create(); Slidalicious.prototype = { initialize: function(){ if(arguments.length > 0) this.element = arguments[0]; if(arguments.length > 1) { this.setOptions(arguments[1]); } else { this.setOptions({}); } this.display_time = this.options.display_time; this.transition_time = this.options.transition_time; this.transition_effect = this.options.transition_effect; this.images = this.options.images; this.links = this.options.links; this.width = this.options.width; this.height = this.options.height; }, setOptions: function(options) { this.options = Object.extend({ transition_effect: Effect.Appear, // transition effect transition_time: 1.0, // seconds display_time: 5.0 // seconds }, options || {}); }, play: function(){ if(this.images.length < 1) return this.error("Please specify at least one image.") if(!this.initialized) this.initializeSlideshow(); if(!this.initialized) return false; this.position = 1; this.setSlide(this.current_slide,0); this.setupSlideshowSize(); if(this.images.length > 1){ this.setSlide(this.next_slide,this.position); this.timer = 0; if(!this.interval) this.interval = setInterval(this.loop.bind(this),1000); } }, loop: function(){ this.timer += 1; if(this.timer >= this.display_time){ this.transition(); this.timer = 0; } }, transition: function(){ this.transition_effect(this.next_slide,{ duration:this.transition_time, afterFinish: this.prepareNext.bind(this)}); }, prepareNext: function(){ this.position += 1; if(this.position >= this.images.length) this.position = 0; var swap = this.current_slide; this.current_slide = this.next_slide; this.next_slide = swap; this.setupBottomSlide(this.current_slide); this.setupTopSlide(this.next_slide); this.setSlide(this.next_slide,this.position); }, setSlide: function(slide,position){ slide.image.src = this.images[position]; if(this.links.length > position && this.links[position]){ slide.href = this.links[position]; } else { slide.href = "#"; } }, setupSlideshowSize: function(){ var dims = Element.getDimensions(this.current_slide.image); var d = {}; if(!this.width) this.width = dims.width; if(!this.height) this.height = dims.height; d.width = this.width + "px"; d.height = this.height + "px"; if(dims.width > 0 && dims.height > 0) Element.setStyle(this.element,d); }, initializeSlideshow: function(){ this.element = $(this.element); if(!this.element) return this.error("Could not find element '"+this.element+"' "); this.element.style.position = "relative"; this.next_slide = document.createElement("A"); this.current_slide = document.createElement("A"); this.next_slide.image = document.createElement("IMG"); this.current_slide.image = document.createElement("IMG"); this.setupTopSlide(this.next_slide); this.setupBottomSlide(this.current_slide); this.next_slide.appendChild(this.next_slide.image); this.current_slide.appendChild(this.current_slide.image); this.element.appendChild(this.current_slide); this.element.appendChild(this.next_slide); this.initialized = true; }, setupTopSlide: function(element){ this.setupSlide(element); element.style.zIndex = 1; element.style.display = "none"; }, setupBottomSlide: function(element){ this.setupSlide(element); element.style.zIndex = 0; element.style.display = ""; }, setupSlide: function(element){ element.style.border = 0; if(element.image) element.image.style.border = 0; element.style.position = "absolute"; element.style.top = 0; element.style.left = 0; }, error: function(msg){ alert("Slidalicious Error: " + msg); return false; } }