| /** |
| Script: Slideshow.js |
| Slideshow - A javascript class for Mootools to stream and animate the presentation of images on your website. |
| |
| License: |
| MIT-style license. |
| |
| Copyright: |
| Copyright (c) 2008 [Aeron Glemann](http://www.electricprism.com/aeron/). |
| |
| Dependencies: |
| Mootools 1.2 Core: Fx.Morph, Fx.Tween, Selectors, Element.Dimensions. |
| Mootools 1.2 More: Assets. |
| */ |
| |
| Slideshow = new Class({ |
| Implements: [Chain, Events, Options], |
| |
| options: {/* |
| onComplete: $empty, |
| onEnd: $empty, |
| onStart: $empty,*/ |
| captions: false, |
| center: true, |
| classes: [], |
| controller: false, |
| delay: 2000, |
| duration: 750, |
| fast: false, |
| height: false, |
| href: '', |
| hu: '', |
| linked: false, |
| loader: {'animate': ['css/loader-#.png', 12]}, |
| loop: true, |
| match: /\?slide=(\d+)$/, |
| overlap: true, |
| paused: false, |
| properties: ['href', 'rel', 'rev', 'title'], |
| random: false, |
| replace: [/(\.[^\.]+)$/, 't$1'], |
| resize: 'width', |
| slide: 0, |
| thumbnails: false, |
| titles: true, |
| transition: function(p){return -(Math.cos(Math.PI * p) - 1) / 2;}, |
| width: false |
| }, |
| |
| /** |
| Constructor: initialize |
| Creates an instance of the Slideshow class. |
| |
| Arguments: |
| element - (element) The wrapper element. |
| data - (array or object) The images and optional thumbnails, captions and links for the show. |
| options - (object) The options below. |
| |
| Syntax: |
| var myShow = new Slideshow(element, data, options); |
| */ |
| |
| initialize: function(el, data, options){ |
| this.setOptions(options); |
| this.slideshow = $(el); |
| if (!this.slideshow) |
| return; |
| this.slideshow.set('styles', {'display': 'block', 'position': 'relative', 'z-index': 0}); |
| var match = window.location.href.match(this.options.match); |
| this.slide = (this.options.match && match) ? match[1].toInt() : this.options.slide; |
| this.counter = this.delay = this.transition = 0; |
| this.direction = 'left'; |
| this.paused = false; |
| if (!this.options.overlap) |
| this.options.duration *= 2; |
| var anchor = this.slideshow.getElement('a') || new Element('a'); |
| if (!this.options.href) |
| this.options.href = anchor.get('href') || ''; |
| if (this.options.hu.length && !this.options.hu.test(/\/$/)) |
| this.options.hu += '/'; |
| if (this.options.fast === true) |
| this.options.fast = 2; |
| |
| // styles |
| |
| var keys = ['slideshow', 'first', 'prev', 'play', 'pause', 'next', 'last', 'images', 'captions', 'controller', 'thumbnails', 'hidden', 'visible', 'inactive', 'active', 'loader']; |
| var values = keys.map(function(key, i){ |
| return this.options.classes[i] || key; |
| }, this); |
| this.classes = values.associate(keys); |
| this.classes.get = function(){ |
| var str = '.' + this.slideshow; |
| for (var i = 0, l = arguments.length; i < l; i++) |
| str += ('-' + this[arguments[i]]); |
| return str; |
| }.bind(this.classes); |
| |
| // data |
| |
| if (!data){ |
| this.options.hu = ''; |
| data = {}; |
| var thumbnails = this.slideshow.getElements(this.classes.get('thumbnails') + ' img'); |
| this.slideshow.getElements(this.classes.get('images') + ' img').each(function(img, i){ |
| var src = img.get('src'); |
| var caption = $pick(img.get('alt'), img.get('title'), ''); |
| var parent = img.getParent(); |
| var properties = (parent.get('tag') == 'a') ? parent.getProperties : {}; |
| var href = img.getParent().get('href') || ''; |
| var thumbnail = (thumbnails[i]) ? thumbnails[i].get('src') : ''; |
| data[src] = {'caption': caption, 'href': href, 'thumbnail': thumbnail}; |
| }); |
| } |
| var loaded = this.load(data); |
| if (!loaded) |
| return; |
| |
| // events |
| |
| this.events = $H({'keydown': [], 'keyup': [], 'mousemove': []}); |
| var keyup = function(e){ |
| switch(e.key){ |
| case 'left': |
| this.prev(e.shift); break; |
| case 'right': |
| this.next(e.shift); break; |
| case 'p': |
| this.pause(); break; |
| } |
| }.bind(this); |
| this.events.keyup.push(keyup); |
| document.addEvent('keyup', keyup); |
| |
| // required elements |
| |
| var el = this.slideshow.getElement(this.classes.get('images')); |
| var images = (el) ? el.empty() : new Element('div', {'class': this.classes.get('images').substr(1)}).inject(this.slideshow); |
| var div = images.getSize(); |
| this.height = this.options.height || div.y; |
| this.width = this.options.width || div.x; |
| images.set({'styles': {'display': 'block', 'height': this.height, 'overflow': 'hidden', 'position': 'relative', 'width': this.width}}); |
| this.slideshow.store('images', images); |
| this.a = this.image = this.slideshow.getElement('img') || new Element('img'); |
| if (Browser.Engine.trident && Browser.Engine.version > 4) |
| this.a.style.msInterpolationMode = 'bicubic'; |
| this.a.set('styles', {'display': 'none', 'position': 'absolute', 'zIndex': 1}); |
| this.b = this.a.clone(); |
| [this.a, this.b].each(function(img){ |
| anchor.clone().cloneEvents(anchor).grab(img).inject(images); |
| }); |
| |
| // optional elements |
| |
| if (this.options.captions) |
| this._captions(); |
| if (this.options.controller) |
| this._controller(); |
| if (this.options.loader) |
| this._loader(); |
| if (this.options.thumbnails) |
| this._thumbnails(); |
| |
| // begin show |
| |
| this._preload(); |
| }, |
| |
| /** |
| Public method: go |
| Jump directly to a slide in the show. |
| |
| Arguments: |
| n - (integer) The index number of the image to jump to, 0 being the first image in the show. |
| |
| Syntax: |
| myShow.go(n); |
| */ |
| |
| go: function(n, direction){ |
| if ((this.slide - 1 + this.data.images.length) % this.data.images.length == n || $time() < this.transition) |
| return; |
| $clear(this.timer); |
| this.delay = 0; |
| this.direction = (direction) ? direction : ((n < this.slide) ? 'right' : 'left'); |
| this.slide = n; |
| if (this.preloader) |
| this.preloader = this.preloader.destroy(); |
| this._preload(this.options.fast == 2 || (this.options.fast == 1 && this.paused)); |
| }, |
| |
| /** |
| Public method: first |
| Goes to the first image in the show. |
| |
| Syntax: |
| myShow.first(); |
| */ |
| |
| first: function(){ |
| this.prev(true); |
| }, |
| |
| /** |
| Public method: prev |
| Goes to the previous image in the show. |
| |
| Syntax: |
| myShow.prev(); |
| */ |
| |
| prev: function(first){ |
| var n = 0; |
| if (!first){ |
| if (this.options.random){ |
| |
| // if it's a random show get the previous slide from the showed array |
| |
| if (this.showed.i < 2) |
| return; |
| this.showed.i -= 2; |
| n = this.showed.array[this.showed.i]; |
| } |
| else |
| n = (this.slide - 2 + this.data.images.length) % this.data.images.length; |
| } |
| this.go(n, 'right'); |
| }, |
| |
| /** |
| Public method: pause |
| Toggles play / pause state of the show. |
| |
| Arguments: |
| p - (undefined, 1 or 0) Call pause with no arguments to toggle the pause state. Call pause(1) to force pause, or pause(0) to force play. |
| |
| Syntax: |
| myShow.pause(p); |
| */ |
| |
| pause: function(p){ |
| if ($chk(p)) |
| this.paused = (p) ? false : true; |
| if (this.paused){ |
| this.paused = false; |
| this.delay = this.transition = 0; |
| this.timer = this._preload.delay(100, this); |
| [this.a, this.b].each(function(img){ |
| ['morph', 'tween'].each(function(p){ |
| if (this.retrieve(p)) this.get(p).resume(); |
| }, img); |
| }); |
| if (this.options.controller) |
| this.slideshow.getElement('.' + this.classes.pause).removeClass(this.classes.play); |
| } |
| else { |
| this.paused = true; |
| this.delay = Number.MAX_VALUE; |
| this.transition = 0; |
| $clear(this.timer); |
| [this.a, this.b].each(function(img){ |
| ['morph', 'tween'].each(function(p){ |
| if (this.retrieve(p)) this.get(p).pause(); |
| }, img); |
| }); |
| if (this.options.controller) |
| this.slideshow.getElement('.' + this.classes.pause).addClass(this.classes.play); |
| } |
| }, |
| |
| /** |
| Public method: next |
| Goes to the next image in the show. |
| |
| Syntax: |
| myShow.next(); |
| */ |
| |
| next: function(last){ |
| var n = (last) ? this.data.images.length - 1 : this.slide; |
| this.go(n, 'left'); |
| }, |
| |
| /** |
| Public method: last |
| Goes to the last image in the show. |
| |
| Syntax: |
| myShow.last(); |
| */ |
| |
| last: function(){ |
| this.next(true); |
| }, |
| |
| /** |
| Public method: load |
| Loads a new data set into the show: will stop the current show, rewind and rebuild thumbnails if applicable. |
| |
| Arguments: |
| data - (array or object) The images and optional thumbnails, captions and links for the show. |
| |
| Syntax: |
| myShow.load(data); |
| */ |
| |
| load: function(data){ |
| this.firstrun = true; |
| this.showed = {'array': [], 'i': 0}; |
| if ($type(data) == 'array'){ |
| this.options.captions = false; |
| data = new Array(data.length).associate(data.map(function(image, i){ return image + '?' + i })); |
| } |
| this.data = {'images': [], 'captions': [], 'hrefs': [], 'thumbnails': []}; |
| for (var image in data){ |
| var obj = data[image] || {}; |
| var caption = (obj.caption) ? obj.caption.trim() : ''; |
| var href = (obj.href) ? obj.href.trim() : ((this.options.linked) ? this.options.hu + image : this.options.href); |
| var thumbnail = (obj.thumbnail) ? obj.thumbnail.trim() : image.replace(this.options.replace[0], this.options.replace[1]); |
| this.data.images.push(image); |
| this.data.captions.push(caption); |
| this.data.hrefs.push(href); |
| this.data.thumbnails.push(thumbnail); |
| } |
| if (this.options.random) |
| this.slide = $random(0, this.data.images.length - 1); |
| |
| // only run when data is loaded dynamically into an existing slideshow instance |
| |
| if (this.options.thumbnails && this.slideshow.retrieve('thumbnails')) |
| this._thumbnails(); |
| if (this.slideshow.retrieve('images')){ |
| [this.a, this.b].each(function(img){ |
| ['morph', 'tween'].each(function(p){ |
| if (this.retrieve(p)) this.get(p).cancel(); |
| }, img); |
| }); |
| this.slide = this.transition = 0; |
| this.go(0); |
| } |
| return this.data.images.length; |
| }, |
| |
| /** |
| Public method: destroy |
| Destroys a Slideshow instance. |
| |
| Arguments: |
| p - (string) The images and optional thumbnails, captions and links for the show. |
| |
| Syntax: |
| myShow.destroy(p); |
| */ |
| |
| destroy: function(p){ |
| this.events.each(function(array, e){ |
| array.each(function(fn){ document.removeEvent(e, fn); }); |
| }); |
| this.pause(1); |
| if (this.options.loader) |
| $clear(this.slideshow.retrieve('loader').retrieve('timer')); |
| if (this.options.thumbnails) |
| $clear(this.slideshow.retrieve('thumbnails').retrieve('timer')); |
| this.slideshow.uid = Native.UID++; |
| if (p) |
| this.slideshow[p](); |
| }, |
| |
| /** |
| Private method: preload |
| Preloads the next slide in the show, once loaded triggers the show, updates captions, thumbnails, etc. |
| */ |
| |
| _preload: function(fast){ |
| if (!this.preloader) |
| this.preloader = new Asset.image(this.options.hu + this.data.images[this.slide], {'onload': function(){ |
| this.store('loaded', true); |
| }}); |
| if (this.preloader.retrieve('loaded') && $time() > this.delay && $time() > this.transition){ |
| if (this.stopped){ |
| if (this.options.captions) |
| this.slideshow.retrieve('captions').get('morph').cancel().start(this.classes.get('captions', 'hidden')); |
| this.pause(1); |
| if (this.end) |
| this.fireEvent('end'); |
| this.stopped = this.end = false; |
| return; |
| } |
| this.image = (this.counter % 2) ? this.b : this.a; |
| this.image.set('styles', {'display': 'block', 'height': 'auto', 'visibility': 'hidden', 'width': 'auto', 'zIndex': this.counter}); |
| ['src', 'height', 'width'].each(function(prop){ |
| this.image.set(prop, this.preloader.get(prop)); |
| }, this); |
| this._resize(this.image); |
| this._center(this.image); |
| var anchor = this.image.getParent(); |
| if (this.data.hrefs[this.slide]) |
| anchor.set('href', this.data.hrefs[this.slide]); |
| else |
| anchor.erase('href'); |
| var text = (this.data.captions[this.slide]) |
| ? this.data.captions[this.slide].replace(/<.+?>/gm, '').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, "'") |
| : ''; |
| this.image.set('alt', text); |
| if (this.options.titles) |
| anchor.set('title', text); |
| if (this.options.loader) |
| this.slideshow.retrieve('loader').fireEvent('hide'); |
| if (this.options.captions) |
| this.slideshow.retrieve('captions').fireEvent('update', fast); |
| if (this.options.thumbnails) |
| this.slideshow.retrieve('thumbnails').fireEvent('update', fast); |
| this._show(fast); |
| this._loaded(); |
| } |
| else { |
| if ($time() > this.delay && this.options.loader) |
| this.slideshow.retrieve('loader').fireEvent('show'); |
| this.timer = (this.paused && this.preloader.retrieve('loaded')) ? null : this._preload.delay(100, this, fast); |
| } |
| }, |
| |
| /** |
| Private method: show |
| Does the slideshow effect. |
| */ |
| |
| _show: function(fast){ |
| if (!this.image.retrieve('morph')){ |
| var options = (this.options.overlap) ? {'duration': this.options.duration, 'link': 'cancel'} : {'duration': this.options.duration / 2, 'link': 'chain'}; |
| $$(this.a, this.b).set('morph', $merge(options, {'onStart': this._start.bind(this), 'onComplete': this._complete.bind(this), 'transition': this.options.transition})); |
| } |
| var hidden = this.classes.get('images', ((this.direction == 'left') ? 'next' : 'prev')); |
| var visible = this.classes.get('images', 'visible'); |
| var img = (this.counter % 2) ? this.a : this.b; |
| if (fast){ |
| img.get('morph').cancel().set(hidden); |
| this.image.get('morph').cancel().set(visible); |
| } |
| else { |
| if (this.options.overlap){ |
| img.get('morph').set(visible); |
| this.image.get('morph').set(hidden).start(visible); |
| } |
| else { |
| var fn = function(hidden, visible){ |
| this.image.get('morph').set(hidden).start(visible); |
| }.pass([hidden, visible], this); |
| hidden = this.classes.get('images', ((this.direction == 'left') ? 'prev' : 'next')); |
| img.get('morph').set(visible).start(hidden).chain(fn); |
| } |
| } |
| }, |
| |
| /** |
| Private method: loaded |
| Run after the current image has been loaded, sets up the next image to be shown. |
| */ |
| |
| _loaded: function(){ |
| this.counter++; |
| this.delay = (this.paused) ? Number.MAX_VALUE : $time() + this.options.duration + this.options.delay; |
| this.direction = 'left'; |
| this.transition = (this.options.fast == 2 || (this.options.fast == 1 && this.paused)) ? 0 : $time() + this.options.duration; |
| if (this.slide + 1 == this.data.images.length && !this.options.loop && !this.options.random) |
| this.stopped = this.end = true; |
| if (this.options.random){ |
| this.showed.i++; |
| if (this.showed.i >= this.showed.array.length){ |
| var n = this.slide; |
| if (this.showed.array.getLast() != n) this.showed.array.push(n); |
| while (this.slide == n) |
| this.slide = $random(0, this.data.images.length - 1); |
| } |
| else |
| this.slide = this.showed.array[this.showed.i]; |
| } |
| else |
| this.slide = (this.slide + 1) % this.data.images.length; |
| if (this.image.getStyle('visibility') != 'visible') |
| (function(){ this.image.setStyle('visibility', 'visible'); }).delay(1, this); |
| if (this.preloader) |
| this.preloader = this.preloader.destroy(); |
| this._preload(); |
| }, |
| |
| /** |
| Private method: center |
| Center an image. |
| */ |
| |
| _center: function(img){ |
| if (this.options.center){ |
| var size = img.getSize(); |
| img.set('styles', {'left': (size.x - this.width) / -2, 'top': (size.y - this.height) / -2}); |
| } |
| }, |
| |
| /** |
| Private method: resize |
| Resizes an image. |
| */ |
| |
| _resize: function(img){ |
| if (this.options.resize){ |
| var h = this.preloader.get('height'), w = this.preloader.get('width'); |
| var dh = this.height / h, dw = this.width / w, d; |
| if (this.options.resize == 'length') |
| d = (dh > dw) ? dw : dh; |
| else |
| d = (dh > dw) ? dh : dw; |
| img.set('styles', {height: Math.ceil(h * d), width: Math.ceil(w * d)}); |
| } |
| }, |
| |
| /** |
| Private method: start |
| Callback on start of slide change. |
| */ |
| |
| _start: function(){ |
| this.fireEvent('start'); |
| }, |
| |
| /** |
| Private method: complete |
| Callback on start of slide change. |
| */ |
| |
| _complete: function(){ |
| if (this.firstrun && this.options.paused){ |
| this.firstrun = false; |
| this.pause(1); |
| } |
| this.fireEvent('complete'); |
| }, |
| |
| /** |
| Private method: captions |
| Builds the optional caption element, adds interactivity. |
| This method can safely be removed if the captions option is not enabled. |
| */ |
| |
| _captions: function(){ |
| if (this.options.captions === true) |
| this.options.captions = {}; |
| var el = this.slideshow.getElement(this.classes.get('captions')); |
| var captions = (el) ? el.empty() : new Element('div', {'class': this.classes.get('captions').substr(1)}).inject(this.slideshow); |
| captions.set({ |
| 'events': { |
| 'update': function(fast){ |
| var captions = this.slideshow.retrieve('captions'); |
| var empty = (this.data.captions[this.slide] === ''); |
| if (fast){ |
| var p = (empty) ? 'hidden' : 'visible'; |
| captions.set('html', this.data.captions[this.slide]).get('morph').cancel().set(this.classes.get('captions', p)); |
| } |
| else { |
| var fn = (empty) ? $empty : function(n){ |
| this.slideshow.retrieve('captions').set('html', this.data.captions[n]).morph(this.classes.get('captions', 'visible')) |
| }.pass(this.slide, this); |
| captions.get('morph').cancel().start(this.classes.get('captions', 'hidden')).chain(fn); |
| } |
| }.bind(this) |
| }, |
| 'morph': $merge(this.options.captions, {'link': 'chain'}) |
| }); |
| this.slideshow.store('captions', captions); |
| }, |
| |
| /** |
| Private method: controller |
| Builds the optional controller element, adds interactivity. |
| This method can safely be removed if the controller option is not enabled. |
| */ |
| |
| _controller: function(){ |
| if (this.options.controller === true) |
| this.options.controller = {}; |
| var el = this.slideshow.getElement(this.classes.get('controller')); |
| var controller = (el) ? el.empty() : new Element('div', {'class': this.classes.get('controller').substr(1)}).inject(this.slideshow); |
| var ul = new Element('ul').inject(controller); |
| $H({'first': 'Shift + Leftwards Arrow', 'prev': 'Leftwards Arrow', 'pause': 'P', 'next': 'Rightwards Arrow', 'last': 'Shift + Rightwards Arrow'}).each(function(accesskey, action){ |
| var li = new Element('li', { |
| 'class': (action == 'pause' && this.options.paused) ? this.classes.play + ' ' + this.classes[action] : this.classes[action] |
| }).inject(ul); |
| var a = this.slideshow.retrieve(action, new Element('a', { |
| 'title': ((action == 'pause') ? this.classes.play.capitalize() + ' / ' : '') + this.classes[action].capitalize() + ' [' + accesskey + ']' |
| }).inject(li)); |
| a.set('events', { |
| 'click': function(action){this[action]();}.pass(action, this), |
| 'mouseenter': function(active){this.addClass(active);}.pass(this.classes.active, a), |
| 'mouseleave': function(active){this.removeClass(active);}.pass(this.classes.active, a) |
| }); |
| }, this); |
| controller.set({ |
| 'events': { |
| 'hide': function(hidden){ |
| if (!this.retrieve('hidden')) |
| this.store('hidden', true).morph(hidden); |
| }.pass(this.classes.get('controller', 'hidden'), controller), |
| 'show': function(visible){ |
| if (this.retrieve('hidden')) |
| this.store('hidden', false).morph(visible); |
| }.pass(this.classes.get('controller', 'visible'), controller) |
| }, |
| 'morph': $merge(this.options.controller, {'link': 'cancel'}) |
| }).store('hidden', false); |
| var keydown = function(e){ |
| if (['left', 'right', 'p'].contains(e.key)){ |
| var controller = this.slideshow.retrieve('controller'); |
| if (controller.retrieve('hidden')) |
| controller.get('morph').set(this.classes.get('controller', 'visible')); |
| switch(e.key){ |
| case 'left': |
| this.slideshow.retrieve((e.shift) ? 'first' : 'prev').fireEvent('mouseenter'); break; |
| case 'right': |
| this.slideshow.retrieve((e.shift) ? 'last' : 'next').fireEvent('mouseenter'); break; |
| default: |
| this.slideshow.retrieve('pause').fireEvent('mouseenter'); break; |
| } |
| } |
| }.bind(this); |
| this.events.keydown.push(keydown); |
| var keyup = function(e){ |
| if (['left', 'right', 'p'].contains(e.key)){ |
| var controller = this.slideshow.retrieve('controller'); |
| if (controller.retrieve('hidden')) |
| controller.store('hidden', false).fireEvent('hide'); |
| switch(e.key){ |
| case 'left': |
| this.slideshow.retrieve((e.shift) ? 'first' : 'prev').fireEvent('mouseleave'); break; |
| case 'right': |
| this.slideshow.retrieve((e.shift) ? 'last' : 'next').fireEvent('mouseleave'); break; |
| default: |
| this.slideshow.retrieve('pause').fireEvent('mouseleave'); break; |
| } |
| } |
| }.bind(this); |
| this.events.keyup.push(keyup); |
| var mousemove = function(e){ |
| var images = this.slideshow.retrieve('images').getCoordinates(); |
| if (e.page.x > images.left && e.page.x < images.right && e.page.y > images.top && e.page.y < images.bottom) |
| this.slideshow.retrieve('controller').fireEvent('show'); |
| else |
| this.slideshow.retrieve('controller').fireEvent('hide'); |
| }.bind(this); |
| this.events.mousemove.push(mousemove); |
| document.addEvents({'keydown': keydown, 'keyup': keyup, 'mousemove': mousemove}); |
| this.slideshow.retrieve('controller', controller).fireEvent('hide'); |
| }, |
| |
| /** |
| Private method: loader |
| Builds the optional loader element, adds interactivity. |
| This method can safely be removed if the loader option is not enabled. |
| */ |
| |
| _loader: function(){ |
| if (this.options.loader === true) |
| this.options.loader = {}; |
| var loader = new Element('div', { |
| 'class': this.classes.get('loader').substr(1), |
| 'morph': $merge(this.options.loader, {'link': 'cancel'}) |
| }).store('hidden', false).store('i', 1).inject(this.slideshow.retrieve('images')); |
| if (this.options.loader.animate){ |
| for (var i = 0; i < this.options.loader.animate[1]; i++) |
| img = new Asset.image(this.options.loader.animate[0].replace(/#/, i)); |
| if (Browser.Engine.trident4 && this.options.loader.animate[0].contains('png')) |
| loader.setStyle('backgroundImage', 'none'); |
| } |
| loader.set('events', { |
| 'animate': function(){ |
| var loader = this.slideshow.retrieve('loader'); |
| var i = (loader.retrieve('i').toInt() + 1) % this.options.loader.animate[1]; |
| loader.store('i', i); |
| var img = this.options.loader.animate[0].replace(/#/, i); |
| if (Browser.Engine.trident4 && this.options.loader.animate[0].contains('png')) |
| loader.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + img + '", sizingMethod="scale")'; |
| else |
| loader.setStyle('backgroundImage', 'url(' + img + ')'); |
| }.bind(this), |
| 'hide': function(){ |
| var loader = this.slideshow.retrieve('loader'); |
| if (!loader.retrieve('hidden')){ |
| loader.store('hidden', true).morph(this.classes.get('loader', 'hidden')); |
| if (this.options.loader.animate) |
| $clear(loader.retrieve('timer')); |
| } |
| }.bind(this), |
| 'show': function(){ |
| var loader = this.slideshow.retrieve('loader'); |
| if (loader.retrieve('hidden')){ |
| loader.store('hidden', false).morph(this.classes.get('loader', 'visible')); |
| if (this.options.loader.animate) |
| loader.store('timer', function(){this.fireEvent('animate');}.periodical(50, loader)); |
| } |
| }.bind(this) |
| }); |
| this.slideshow.retrieve('loader', loader).fireEvent('hide'); |
| }, |
| |
| /** |
| Private method: thumbnails |
| Builds the optional thumbnails element, adds interactivity. |
| This method can safely be removed if the thumbnails option is not enabled. |
| */ |
| |
| _thumbnails: function(){ |
| if (this.options.thumbnails === true) |
| this.options.thumbnails = {}; |
| var el = this.slideshow.getElement(this.classes.get('thumbnails')); |
| var thumbnails = (el) ? el.empty() : new Element('div', {'class': this.classes.get('thumbnails').substr(1)}).inject(this.slideshow); |
| thumbnails.setStyle('overflow', 'hidden'); |
| var ul = new Element('ul', {'tween': {'link': 'cancel'}}).inject(thumbnails); |
| this.data.thumbnails.each(function(thumbnail, i){ |
| var li = new Element('li').inject(ul); |
| var a = new Element('a', { |
| 'events': { |
| 'click': function(i){ |
| this.go(i); |
| return false; |
| }.pass(i, this), |
| 'loaded': function(){ |
| this.data.thumbnails.pop(); |
| if (!this.data.thumbnails.length){ |
| var div = thumbnails.getCoordinates(); |
| var props = thumbnails.retrieve('props'); |
| var limit = 0, pos = props[1], size = props[2]; |
| thumbnails.getElements('li').each(function(li){ |
| var li = li.getCoordinates(); |
| if (li[pos] > limit) limit = li[pos]; |
| }, this); |
| thumbnails.store('limit', div[size] + div[props[0]] - limit); |
| } |
| }.bind(this) |
| }, |
| 'href': this.options.hu + this.data.images[i], |
| 'morph': $merge(this.options.thumbnails, {'link': 'cancel'}) |
| }).inject(li); |
| if (this.data.captions[i] && this.options.titles) |
| a.set('title', this.data.captions[i].replace(/<.+?>/gm, '').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, "'")); |
| var img = new Asset.image(this.options.hu + thumbnail, { |
| 'onload': function(){this.fireEvent('loaded');}.bind(a) |
| }).inject(a); |
| }, this); |
| thumbnails.set('events', { |
| 'scroll': function(n, fast){ |
| var div = this.getCoordinates(); |
| var ul = this.getElement('ul').getPosition(); |
| var props = this.retrieve('props'); |
| var axis = props[3], delta, pos = props[0], size = props[2], value; |
| var tween = this.getElement('ul').get('tween', {'property': pos}); |
| if ($chk(n)){ |
| var li = this.getElements('li')[n].getCoordinates(); |
| delta = div[pos] + (div[size] / 2) - (li[size] / 2) - li[pos] |
| value = (ul[axis] - div[pos] + delta).limit(this.retrieve('limit'), 0); |
| if (fast) |
| tween.set(value); |
| else |
| tween.start(value); |
| } |
| else{ |
| var area = div[props[2]] / 3, page = this.retrieve('page'), velocity = -0.2; |
| if (page[axis] < (div[pos] + area)) |
| delta = (page[axis] - div[pos] - area) * velocity; |
| else if (page[axis] > (div[pos] + div[size] - area)) |
| delta = (page[axis] - div[pos] - div[size] + area) * velocity; |
| if (delta){ |
| value = (ul[axis] - div[pos] + delta).limit(this.retrieve('limit'), 0); |
| tween.set(value); |
| } |
| } |
| }.bind(thumbnails), |
| 'update': function(fast){ |
| var thumbnails = this.slideshow.retrieve('thumbnails'); |
| thumbnails.getElements('a').each(function(a, i){ |
| if (i == this.slide){ |
| if (!a.retrieve('active', false)){ |
| a.store('active', true); |
| var active = this.classes.get('thumbnails', 'active'); |
| if (fast) a.get('morph').set(active); |
| else a.morph(active); |
| } |
| } |
| else { |
| if (a.retrieve('active', true)){ |
| a.store('active', false); |
| var inactive = this.classes.get('thumbnails', 'inactive'); |
| if (fast) a.get('morph').set(inactive); |
| else a.morph(inactive); |
| } |
| } |
| }, this); |
| if (!thumbnails.retrieve('mouseover')) |
| thumbnails.fireEvent('scroll', [this.slide, fast]); |
| }.bind(this) |
| }) |
| var div = thumbnails.getCoordinates(); |
| thumbnails.store('props', (div.height > div.width) ? ['top', 'bottom', 'height', 'y'] : ['left', 'right', 'width', 'x']); |
| var mousemove = function(e){ |
| var div = this.getCoordinates(); |
| if (e.page.x > div.left && e.page.x < div.right && e.page.y > div.top && e.page.y < div.bottom){ |
| this.store('page', e.page); |
| if (!this.retrieve('mouseover')){ |
| this.store('mouseover', true); |
| this.store('timer', function(){this.fireEvent('scroll');}.periodical(50, this)); |
| } |
| } |
| else { |
| if (this.retrieve('mouseover')){ |
| this.store('mouseover', false); |
| $clear(this.retrieve('timer')); |
| } |
| } |
| }.bind(thumbnails); |
| this.events.mousemove.push(mousemove); |
| document.addEvent('mousemove', mousemove); |
| this.slideshow.store('thumbnails', thumbnails); |
| } |
| }); |