/* --- name: "SlideShow" description: "Extensible mid-level class that manages transitions of elements that share the same space, typically for slideshows, tabs, and galleries." license: "MIT-style license." authors: "Ryan Florence " requires: - Core/Fx.Tween - Core/Slick.Parser - Loop/Loop provides: - SlideShow ... */ ;(function(){ var SlideShow = this.SlideShow = new Class({ Implements: [Options, Events, Loop], options: { /* onShow: function(){}, onShowComplete: function(){}, onReverse: function(){}, onPlay: function(){}, onPause: function(){}, */ delay: 7000, transition: 'crossFade', duration: 500, autoplay: false, dataAttribute: 'data-slideshow', selector: '> *', initialSlideIndex: 0 }, transitioning: false, reversed: false, initialize: function(element, options, noSetup){ this.element = document.id(element); this.setOptions(options); if (!noSetup) this.setup(); }, setup: function(options){ if (options) this.setOptions(options); this.slides = this.element.getElements(this.options.selector); this.setupElement().setupSlides(); this.current = this.current || this.slides[this.options.initialSlideIndex]; this.index = this.current.retrieve('slideshow-index'); this.setLoop(this.show.pass(this.reversed ? 'previous' : 'next', this), this.options.delay); if (this.options.autoplay) this.play(); return this; }, show: function(slide, options){ if (slide == 'next' || slide == 'previous') slide = this[slide + 'Slide'](); if (typeof slide == 'number') slide = this.slides[slide]; if (slide == this.current || this.transitioning) return this; this.transitioning = true; this.current.store('slideshow:oldStyles', this.current.get('style')); var transition = (options && options.transition) ? options.transition : slide.retrieve('slideshow-transition'), duration = (options && options.duration) ? options.duration : slide.retrieve('slideshow-duration'), previous = this.current.setStyle('z-index', 1), next = this.reset(slide).setStyle('z-index', 0), nextIndex = this.index = next.retrieve('slideshow-index') slideData = { previous: { element: previous, index: previous.retrieve('slideshow-index') }, next: { element: next, index: nextIndex } }; this.fireEvent('show', slideData); SlideShow.transitions[transition]({ previous: previous, next: next, duration: duration, instance: this }); (function(){ previous.setStyle('display', 'none'); this.fireEvent('showComplete', slideData); this.transitioning = false; }).bind(this).delay(duration); this.current = next; return this; }, play: function(){ this.startLoop(); this.fireEvent('play'); return this; }, pause: function(){ this.stopLoop(); this.fireEvent('pause'); return this; }, reverse: function(){ this.setLoop(this.show.pass(this.reversed ? 'next' : 'previous', this), this.options.delay); this.reversed = !this.reversed; this.fireEvent('reverse'); return this; }, setupElement: function(){ this.storeData(this.element); this.options.duration = this.element.retrieve('slideshow-duration'); this.options.transition = this.element.retrieve('slideshow-transition'); this.options.delay = this.element.retrieve('slideshow-delay'); if (this.element.getStyle('position') == 'static') this.element.setStyle('position', 'relative'); return this; }, setupSlides: function(){ this.slides.each(function(slide, index){ slide.store('slideshow-index', index).store('slideshow:oldStyles', slide.get('style')); this.storeData(slide); slide.setStyle('display', (this.current || index == this.options.initialSlideIndex) ? '' : 'none'); }, this); return this; }, storeData: function(element){ var ops = this.options; // default options element.store('slideshow-transition', ops.transition); element.store('slideshow-duration', ops.duration); if (element == this.element) element.store('slideshow-delay', ops.delay); // override from data attribute var data = element.get(this.options.dataAttribute); if (!data) return this; Slick.parse(data).expressions[0].each(function(option){ element.store('slideshow-' + option.tag, option.pseudos[0].key); }); return this; }, reset: function(slide){ return slide.set('style', slide.retrieve('slideshow:oldStyles')); }, nextSlide: function(){ return this.slides[this.index + 1] || this.slides[0]; }, previousSlide: function(){ return this.slides[this.index - 1] || this.slides.getLast(); }, toElement: function(){ return this.element; } }); SlideShow.transitions = {}; SlideShow.defineTransition = function(name, fn){ SlideShow.transitions[name] = fn; }; SlideShow.defineTransitions = function(transitions){ Object.each(transitions, function(item, index){ SlideShow.defineTransition(index, item); }); }; })(); // element extensions Element.Properties.slideshow = { set: function(options){ this.get('slideshow').setup(options); return this; }, get: function(){ var instance = this.retrieve('slideshow'); if (!instance){ instance = new SlideShow(this, {}, true); this.store('slideshow', instance); } return instance; } }; Element.implement({ playSlideShow: function(options){ this.get('slideshow').setup(options).play(); return this; }, pauseSlideShow: function(){ this.get('slideshow').pause(); return this; } }); // 19 transitions :D SlideShow.defineTransitions({ none: function(data){ data.previous.setStyle('display', 'none'); return this; }, fade: function(data){ data.previous.set('tween', {duration: data.duration}).fade('out'); return this; }, crossFade: function(data){ data.previous.set('tween', {duration: data.duration}).fade('out'); data.next.set('tween', {duration: data.duration}).fade('in'); return this; }, fadeThroughBackground: function(data){ var half = data.duration / 2; data.next.set('tween', {duration: half}).fade('hide'); data.previous.set('tween',{ duration: half, onComplete: function(){ data.next.fade('in'); } }).fade('out'); return this; } }); (function(){ function getStyles(direction){ return { property: (direction == 'left' || direction == 'right') ? 'left' : 'top', inverted: (direction == 'left' || direction == 'up') ? 1 : -1 }; } function go(type, styles, data){ var tweenOptions = {duration: data.duration, unit: '%'}; if (type == 'blind') { data.next.setStyle('z-index', 2); } if (type != 'slide') { data.next .set('tween', tweenOptions) .setStyle(styles.property, 100 * styles.inverted + '%'); data.next.tween(styles.property, 0); } if (type != 'blind'){ data.previous .set('tween', tweenOptions) .tween(styles.property, -(100 * styles.inverted)); } } ['left', 'right', 'up', 'down'].each(function(direction){ var capitalized = direction.capitalize(), blindName = 'blind' + capitalized, slideName = 'slide' + capitalized; [ ['push' + capitalized, (function(){ var styles = getStyles(direction); return function(data){ go('push', styles, data); } }())], [blindName, (function(){ var styles = getStyles(direction); return function(data){ go('blind', styles, data); } }())], [slideName, (function(){ var styles = getStyles(direction); return function(data){ go('slide', styles, data); } }())], [blindName + 'Fade', function(data){ this.fade(data)[blindName](data); return this; }] ].each(function(transition){ SlideShow.defineTransition(transition[0], transition[1]); }); }); })();