/** 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: 7000, 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, "'") : ''; 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, "'")); 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); } });