/* This file is part of JonDesign's SmoothGallery v2.0. 3.2.0 JonDesign's SmoothGallery 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 3 of the License, or (at your option) any later version. JonDesign's SmoothGallery 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 JonDesign's SmoothGallery; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/) Contributed code by: - Christian Ehret (bugfix) - Nitrix (bugfix) - Valerio from Mad4Milk for his great help with the carousel scrolling and many other things. - Archie Cowan for helping me find a bugfix on carousel inner width problem. - Tomocchino from #mootools for the preloader class Many thanks to: - The mootools team for the great mootools lib, and it's help and support throughout the project. */ var $extend = function(){ var args = arguments; if (!args[1]) args = [this, args[0]]; for (var property in args[1]) args[0][property] = args[1][property]; return args[0]; }; var Abstract = function(obj){ obj = obj || {}; obj.extend = $extend; return obj; }; var Class = function(properties){ var klass = function(){ return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this; }; $extend(klass, this); klass.prototype = properties; klass.constructor = Class; return klass; }; Class.empty = function(){}; Class.prototype = { /* Property: extend Returns the copy of the Class extended with the passed in properties. Arguments: properties - the properties to add to the base class in this new Class. Example: (start code) var Animal = new Class({ initialize: function(age){ this.age = age; } }); var Cat = Animal.extend({ initialize: function(name, age){ this.parent(age); //will call the previous initialize; this.name = name; } }); var myCat = new Cat('Micia', 20); alert(myCat.name); //alerts 'Micia' alert(myCat.age); //alerts 20 (end) */ extend: function(properties){ var proto = new this(null); for (var property in properties){ var pp = proto[property]; proto[property] = Class.Merge(pp, properties[property]); } return new Class(proto); }, /* Property: implement Implements the passed in properties to the base Class prototypes, altering the base class, unlike . Arguments: properties - the properties to add to the base class. Example: (start code) var Animal = new Class({ initialize: function(age){ this.age = age; } }); Animal.implement({ setName: function(name){ this.name = name } }); var myAnimal = new Animal(20); myAnimal.setName('Micia'); alert(myAnimal.name); //alerts 'Micia' (end) */ implement: function(){ for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]); } }; //internal Class.Merge = function(previous, current){ if (previous && previous != current){ var type = $type(current); if (type != $type(previous)) return current; switch(type){ case 'function': var merged = function(){ this.parent = arguments.callee.parent; return current.apply(this, arguments); }; merged.parent = previous; return merged; case 'object': return $merge(previous, current); } } return current; }; /* Script: Class.Extras.js Contains common implementations for custom classes. In Mootools is implemented in , and and many more. License: MIT-style license. */ /* Class: Chain An "Utility" Class. Its methods can be implemented with into any . Currently implemented in , and . In for example, is used to execute a list of function, one after another, once the effect is completed. The functions will not be fired all togheter, but one every completion, to create custom complex animations. Example: (start code) var myFx = new Fx.Style('element', 'opacity'); myFx.start(1,0).chain(function(){ myFx.start(0,1); }).chain(function(){ myFx.start(1,0); }).chain(function(){ myFx.start(0,1); }); //the element will appear and disappear three times (end) */ var Chain = new Class({ /* Property: chain adds a function to the Chain instance stack. Arguments: fn - the function to append. */ chain: function(fn){ this.chains = this.chains || []; this.chains.push(fn); return this; }, /* Property: callChain Executes the first function of the Chain instance stack, then removes it. The first function will then become the second. */ callChain: function(){ if (this.chains && this.chains.length) this.chains.shift().delay(10, this); }, /* Property: clearChain Clears the stack of a Chain instance. */ clearChain: function(){ this.chains = []; } }); var Options = new Class({ /* Property: setOptions sets this.options Arguments: defaults - object; the default set of options options - object; the user entered options. can be empty too. Note: if your Class has implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event. */ setOptions: function(){ this.options = $merge.apply(null, [this.options].extend(arguments)); if (this.addEvent){ for (var option in this.options){ if ($type(this.options[option] == 'function') && (/^on[A-Z]/).test(option)) this.addEvent(option, this.options[option]); } } return this; } }); var Events = new Class({ /* Property: addEvent adds an event to the stack of events of the Class instance. Arguments: type - string; the event name (e.g. 'onComplete') fn - function to execute */ addEvent: function(type, fn){ if (fn != Class.empty){ this.$mooevents = this.$mooevents || {}; this.$mooevents[type] = this.$mooevents[type] || []; this.$mooevents[type].include(fn); } return this; }, /* Property: fireEvent fires all events of the specified type in the Class instance. Arguments: type - string; the event name (e.g. 'onComplete') args - array or single object; arguments to pass to the function; if more than one argument, must be an array delay - (integer) delay (in ms) to wait to execute the event Example: (start code) var Widget = new Class({ initialize: function(arg1, arg2){ ... this.fireEvent("onInitialize", [arg1, arg2], 50); } }); Widget.implement(new Events); (end) */ fireEvent: function(type, args, delay){ if (this.$mooevents && this.$mooevents[type]){ this.$mooevents[type].each(function(fn){ fn.create({'bind': this, 'delay': delay, 'arguments': args})(); }, this); } return this; }, /* Property: removeEvent removes an event from the stack of events of the Class instance. Arguments: type - string; the event name (e.g. 'onComplete') fn - function that was added */ removeEvent: function(type, fn){ if (this.$mooevents && this.$mooevents[type]) this.$mooevents[type].remove(fn); return this; } }); // declaring the class var gallery = { initialize: function(element, options) { this.setOptions({ showArrows: true, showCarousel: true, showInfopane: true, embedLinks: true, fadeDuration: 500, timed: false, delay: 9000, preloader: true, preloaderImage: true, preloaderErrorImage: true, /* Data retrieval */ manualData: [], populateFrom: false, populateData: true, destroyAfterPopulate: true, elementSelector: "div.imageElement", titleSelector: "h2", subtitleSelector: "p", linkSelector: "a.open", imageSelector: "img.full", thumbnailSelector: "img.thumbnail", defaultTransition: 'continuousvertical', /* InfoPane options */ slideInfoZoneOpacity: 0.7, slideInfoZoneSlide: true, /* Carousel options */ carouselMinimizedOpacity: 0.4, carouselMinimizedHeight: 20, carouselMaximizedOpacity: 0.9, thumbHeight: 75, thumbWidth: 100, thumbSpacing: 10, thumbIdleOpacity: 0.6, textShowCarousel: 'Ads', showCarouselLabel: true, thumbCloseCarousel: true, useThumbGenerator: false, thumbGenerator: 'resizer.php', useExternalCarousel: false, carouselElement: false, carouselHorizontal: true, activateCarouselScroller: true, carouselPreloader: true, textPreloadingCarousel: 'Loading...', /* CSS Classes */ baseClass: 'jdGallery', withArrowsClass: 'withArrows', /* Plugins: HistoryManager */ useHistoryManager: false, customHistoryKey: false }, options); this.fireEvent('onInit'); this.currentIter = 0; this.lastIter = 0; this.maxIter = 0; this.galleryElement = element; this.galleryData = this.options.manualData; this.galleryInit = 1; this.galleryElements = Array(); this.thumbnailElements = Array(); this.galleryElement.addClass(this.options.baseClass); this.populateFrom = element; if (this.options.populateFrom) this.populateFrom = this.options.populateFrom; if (this.options.populateData) this.populateData(); element.style.display="block"; if (this.options.useHistoryManager) this.initHistory(); if (this.options.embedLinks) { this.currentLink = new Element('a').addClass('open').setProperties({ href: '#', title: '' }).injectInside(element); if ((!this.options.showArrows) && (!this.options.showCarousel)) this.galleryElement = element = this.currentLink; else this.currentLink.setStyle('display', 'none'); } this.constructElements(); if ((this.galleryData.length>1)&&(this.options.showArrows)) { var leftArrow = new Element('a').addClass('left').addEvent( 'click', this.prevItem.bind(this) ).injectInside(element); var rightArrow = new Element('a').addClass('right').addEvent( 'click', this.nextItem.bind(this) ).injectInside(element); this.galleryElement.addClass(this.options.withArrowsClass); } this.loadingElement = new Element('div').addClass('loadingElement').injectInside(element); if (this.options.showInfopane) this.initInfoSlideshow(); if (this.options.showCarousel) this.initCarousel(); this.doSlideShow(1); }, populateData: function() { currentArrayPlace = this.galleryData.length; options = this.options; var data = $A(this.galleryData); data.extend(this.populateGallery(this.populateFrom, currentArrayPlace)); this.galleryData = data; this.fireEvent('onPopulated'); }, populateGallery: function(element, startNumber) { var data = []; options = this.options; currentArrayPlace = startNumber; element.getElements(options.elementSelector).each(function(el) { elementDict = { image: el.getElement(options.imageSelector).getProperty('src'), number: currentArrayPlace, transition: this.options.defaultTransition }; elementDict.extend = $extend; if ((options.showInfopane) | (options.showCarousel)) elementDict.extend({ title: el.getElement(options.titleSelector).innerHTML, description: el.getElement(options.subtitleSelector).innerHTML }); if (options.embedLinks) elementDict.extend({ link: el.getElement(options.linkSelector).href||false, linkTitle: el.getElement(options.linkSelector).title||false, linkTarget: el.getElement(options.linkSelector).getProperty('target')||false }); if ((!options.useThumbGenerator) && (options.showCarousel)) elementDict.extend({ thumbnail: el.getElement(options.thumbnailSelector).getProperty('src') }); else if (options.useThumbGenerator) elementDict.extend({ thumbnail: options.thumbGenerator + '?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight }); data.extend([elementDict]); currentArrayPlace++; if (this.options.destroyAfterPopulate) el.remove(); }); return 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.fireEvent('onPreviousCalled'); this.nextIter = this.currentIter-1; if (this.nextIter <= -1) this.nextIter = this.maxIter - 1; this.galleryInit = 0; this.goTo(this.nextIter); }, goTo: function(num) { this.clearTimer(); if(this.options.preloader) { this.galleryElements[num].load(); if (num==0) this.galleryElements[this.maxIter - 1].load(); else this.galleryElements[num - 1].load(); if (num==(this.maxIter - 1)) this.galleryElements[0].load(); else this.galleryElements[num + 1].load(); } if (this.options.embedLinks) this.clearLink(); if (this.options.showInfopane) { this.slideInfoZone.clearChain(); this.hideInfoSlideShow().chain(this.changeItem.pass(num, this)); } else this.currentChangeDelay = this.changeItem.delay(500, this, num); if (this.options.embedLinks) this.makeLink(num); this.prepareTimer(); /*if (this.options.showCarousel) this.clearThumbnailsHighlights();*/ }, changeItem: function(num) { this.fireEvent('onStartChanging'); this.galleryInit = 0; if (this.currentIter != num) { for(i=0;i' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ": " + myself.relatedImage.title); }.pass(currentImg, this), 'mouseout': function (myself) { myself.clearTimer(); myself.start(this.options.thumbIdleOpacity); }.pass(currentImg, this), 'click': function (myself) { this.goTo(myself.relatedImage.number); if (this.options.thumbCloseCarousel) this.hideCarousel(); }.pass(currentImg, this) }); currentImg.relatedImage = this.galleryData[i]; this.thumbnailElements[parseInt(i)] = currentImg; } }, log: function(value) { if(console.log) console.log(value); }, preloadThumbnails: function() { var thumbnails = []; for(i=0;i oldPos) newFx.start({opacity: 1}); else { newFx.set({opacity: 1}); oldFx.start({opacity: 0}); } }, crossfade: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration; newFx.start({opacity: 1}); oldFx.start({opacity: 0}); }, fadebg: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration / 2; oldFx.start({opacity: 0}).chain(newFx.start.pass([{opacity: 1}], newFx)); } }); /* All code copyright 2007 Jonathan Schemoul */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: Preloader (class) * Simple class for preloading images with support for progress reporting * Copyright 2007 Tomocchino. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ var Preloader = new Class({ Implements: [Events, Options], options: { root : '', period : 100 }, initialize: function(options){ this.setOptions(options); }, load: function(sources) { this.index = 0; this.images = []; this.sources = this.temps = sources; this.total = this. sources.length; this.fireEvent('onStart', [this.index, this.total]); this.timer = this.progress.periodical(this.options.period, this); this.sources.each(function(source, index){ this.images[index] = new Asset.image(this.options.root + source, { 'onload' : function(){ this.index++; if(this.images[index]) this.fireEvent('onLoad', [this.images[index], index, source]); }.bind(this), 'onerror' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this), 'onabort' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this) }); }, this); }, progress: function() { this.fireEvent('onProgress', [Math.min(this.index, this.total), this.total]); if(this.index >= this.total) this.complete(); }, complete: function(){ $clear(this.timer); this.fireEvent('onComplete', [this.images]); }, cancel: function(){ $clear(this.timer); } }); Preloader.implement(new Events, new Options); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: formatString (function) * Original name: Yahoo.Tools.printf * Copyright Yahoo. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function formatString() { var num = arguments.length; var oStr = arguments[0]; for (var i = 1; i < num; i++) { var pattern = "\\{" + (i-1) + "\\}"; var re = new RegExp(pattern, "g"); oStr = oStr.replace(re, arguments[i]); } return oStr; }