// -----------------------------------------------------------------------------------
//
//	TickerBox v0.5 BETA
//	by Alexandre Marinho - http://www.cuboestudioweb.com/
//	23/04/2008
//
//	For more information on this script, visit:
//	http://www.cuboestudioweb.com/projects/tickerbox
//
//	Licensed under the The GNU General Public License - http://www.opensource.org/licenses/gpl-license.php
//
//
// -----------------------------------------------------------------------------------


var Ticker = Class.create({
	options : {
		mode : 'normal',
		containerWidth : '320px',
		containerHeight : '250px',
		filePrevImage : "images/prev.gif",
		fileNextImage : "images/next.gif",
		controls : true,
		label : true,
		pauseTime : 5,
		animationTime : 0.5,
		showBorder : true,
		background : 'transparent'
	},
	
	initialize: function(container,options) {
		this.container = (typeof(container)=='string') ? $(container) : container;
		this.container.addClassName('ticker');
		this.photos = $A(this.container.getElementsByTagName('img'));
		this.hideAllPhotos();
		this.options = Object.extend(
			Object.clone(this.options),
			options || { }
		);
		this.container.setStyle({
			width : this.options.containerWidth,
			height : this.options.containerHeight,
			backgroundColor : this.options.background
		});
		if(!this.options.showBorder){
			this.container.setStyle({
				border : 'none'
			})
		}
		
		this.countPhotos = this.photos.length;
		
		this.timeout = null;
		this.index = 0;
		this.createElements();
		// Periodical Executer to check when all the images has loaded
		this.pe = new PeriodicalExecuter(this.checkImagesState.bind(this), 0);
		
	},
	
	createElements : function(){
		//creates the loading image
		this.container.insert(new Element('div',{
			'class' : 'ticker-loading'
		}));
		this.load = this.container.getElementsByClassName('ticker-loading')[0];
		
		if (this.options.controls) {
			//creates the previous image button
			this.container.insert(new Element('img',{
				'class':'prev',
				'src' : this.options.filePrevImage
			}))
			this.prev = this.container.getElementsByClassName('prev')[0];
			new Effect.Opacity(this.prev,{to:0.2,duration:0});
			Event.observe(this.prev,'mouseover',function(){
				new Effect.Opacity(this.prev,{
					to:1,
					duration:0
				})
			}.bind(this))
			Event.observe(this.prev,'mouseout',function(){
				new Effect.Opacity(this.prev,{
					to:0.2,
					duration:0
				})
			}.bind(this))
			
			// creates the next image button
			this.container.insert(new Element('img',{
				'class':'next',
				'src' : this.options.fileNextImage
			}))
			this.next = this.container.getElementsByClassName('next')[0];
			new Effect.Opacity(this.next,{to:0.2,duration:0});
			Event.observe(this.next,'mouseover',function(){
				new Effect.Opacity(this.next,{
					to:1,
					duration:0
				})
			}.bind(this))
			Event.observe(this.next,'mouseout',function(){
				new Effect.Opacity(this.next,{
					to:0.2,
					duration:0
				})
			}.bind(this))
		}
		
		//create comments element
		this.container.insert(new Element('div',{
				'class':'comments'
		}))
		this.comments = this.container.getElementsByClassName('comments')[0];
		new Effect.Opacity(this.comments,{to:0.5,duration:0});
		
	},
	
	/**
	 * checkImagesState()
	 *
	 * Checks if the ticker images has been loaded
	 */
	checkImagesState: function() {
		if (this.hasImagesLoaded()) {
			this.pe.stop();
			this.setPositions()
			Element.hide(this.load);
			this.show();
		}    
	},
	
	setPositions : function(){
		var maxWidth = 0
		var minWidth = 999999
		var maxHeight = 0
		var minHeight = 999999
		this.photos.each(function(item){
			maxWidth = (maxWidth < item.getWidth()) ? item.getWidth() : maxWidth
			maxHeight = (maxHeight < item.getHeight()) ? item.getHeight() : maxHeight
			minWidth = (minWidth > item.getWidth()) ? item.getWidth() : minHeight
			minHeight = (minHeight > item.getHeight()) ? item.getHeight() : minHeight
			item.setStyle({
				marginLeft: '-'+item.getWidth()/2+'px',
				marginTop: '-'+item.getHeight()/2+'px'
			})
		});
		switch(this.options.mode){
			case 'normal' : 
				this.container.setStyle({
					width: maxWidth + 'px',
					height: maxHeight + 'px'
				})
				break
			case 'fixed' :
				break;
			case 'loose' :
				this.container.setStyle({
					width: maxWidth + 'px',
					height: maxHeight + 'px'
				}).addClassName('loose')
				break;
		}
	},

	/**
	 * show()
	 *
	 * Show the current picture
	 */
	show: function() {
		this.lockButtons();
		this.comments.innerHTML = this.photos[this.index].alt;
		new Effect.Appear(this.photos[this.index],{
				duration:this.options.animationTime,
				afterFinishInternal: function(){
					if(this.photos[this.index].alt!="" && this.options.label){
						Element.show(this.comments)
						this.comments.setStyle({top:this.container.getHeight()+'px'})
						new Effect.Move(this.comments, {
							x:0,
							y:-40,
							duration:0.2,
							afterFinishInternal:this.unLockButtons()
						});
					}else{
						this.unLockButtons();
					}
					this.timeout = setTimeout(function(){this.hide()}.bind(this),this.options.pauseTime*1000);
				}.bind(this)
			}
		);
	},
	
	/**
	 * hide()
	 *
	 * Starts to hide comments and photo
	 * 
	 * @param boolean prev
	 * @return void
	 */
	hide: function(prev) {		
		this.lockButtons();
		if (this.photos[this.index].alt != "" && this.options.label) {
			new Effect.Move(this.comments, {
				x: 0,
				y: 40,
				duration: 0.2,
				afterFinishInternal: function(){
					Element.hide(this.comments);
					this.fadePhoto(prev);
				}.bind(this)
			});
		}
		else {
			this.fadePhoto(prev);
		}
	},
	
	
	/**
	 * fadePhoto()
	 *
	 * Does the fade effect in the actual image
	 * 
	 * @param boolean prev
	 */
	fadePhoto : function(prev){
        new Effect.Fade(this.photos[this.index], {
            duration: this.options.animationTime,
            afterFinishInternal: function(){
                Element.hide(this.photos[this.index]);
                if (prev == true) 
                    this.index = (this.index == 0) ? this.countPhotos - 1 : this.index - 1;
                else 
                    this.index = (this.index == this.countPhotos - 1) ? 0 : this.index + 1;
                this.show();
            }.bind(this)
        });
	},
	
	/**
	 * lockButtons()
	 *
	 * Lock the prev, next image buttons
	 */
	lockButtons: function(){        
        if (this.options.controls) {
            this.prev.onclick = function(){
            }
            this.next.onclick = function(){
            }
        }
	},
	
	/**
	 * unLockButtons()
	 *
	 * Unlock the prev, next image buttons
	 */
	unLockButtons: function(){
		if (this.options.controls) {
			this.prev.onclick = function(){
				clearTimeout(this.timeout);
				this.hide(true);
			}.bind(this);
			this.next.onclick = function(p){
				clearTimeout(this.timeout);
				this.hide(false);
			}.bind(this);
		}
	},
	
	/**
	 * hideAllPhotos()
	 *
	 * Hide all ticker images before it starts.
	 * 
	 * @return void
	 */
	hideAllPhotos: function() {
		this.photos.each(function(item){
			Element.hide(item);
			item.addClassName('photo');
		}.bind(this));
	},
	
	/**
	 * hasImagesLoaded()
	 *
	 * Checks wether all the images
	 * in the document have loaded.
	 *
	 * @author John-David Dalton <john.david.dalton[at]gmail[dot]com>
	 * @return boolean
	 * @todo see if document.images will work instead of $$('img')
	 * @link http://www.bigbold.com/snippets/posts/show/89
	 * @link http://talideon.com/weblog/2005/02/detecting-broken-images-js.cfm
	 */
	hasImagesLoaded: function(){
	  return this.photos.all(function(img){
		return (img.readyState == 'complete' || img.complete || 
		  !(typeof img.naturalWidth == "number" || img.naturalWidth == 0));
	  });
	}

});

startTicker = function(){
	$$('.tickerbox').each(function(ob){
		new Ticker(ob);
	});
}
Event.observe(document,"dom:loaded", startTicker);
