/*  Noopty Slideshow & Noopty Image Scaler version 1.0
 *  (c) 2010 Outpost Design
 *
 *  SVN FILE: $Id: noopty.js 558 2010-05-06 13:50:01Z michaelklauss $
 *--------------------------------------------------------------------------*/
 
var Noopty = Class.create({	
	container:      null, 
	slides:         [],
	currentSlide:   0,
	nextSlide:      0,
	initialize: function(args) {
		// update default options
		var h = $H(args);
		h.each(function(item) {
			if( typeof(this.options[item.key]) != 'undefined' ) {
				this.options[item.key] = item.value ;
			}
		}.bind(this));
		// set slide container element
		if(this.options.containerId!=null) {
			this.container = $(this.options.containerId);
		}
		// select slide elements
		if(this.options.slide!=null) {
			this.slides = this.container.select(this.options.slide);	
		} else {
			this.slides = this.container.childElements();
		}
		this.slides.each(function(s) {s.hide();});	
		if(this.options.shuffle){this.slides.shuffle();}
		
		// set a primary image as the default image
		if(this.options.primary==true) {
			for(i=0;i<this.slides.length;i++) {
				if(this.slides[i].readAttribute('primary')=='true') {
					this.currentSlide = i;
					break;
				}
			}
		}
		if(this.options.before!=null) {
			this.options.before(this.slides[this.currentSlide]);
		}
		this.slides[this.currentSlide].show();
		
		// attach UI events
		this.attachui();
	},
	attachui: function() { 
		if(this.options.hover) {
			this.slides.each(function(item) {
				if(this.options.mouseenter != null) {
					item.observe('mouseenter',function(evt){
						this.stop();
						this.options.mouseenter(evt);
					}.bindAsEventListener(this));
				}
				if(this.options.mouseleave != null) {				
					item.observe('mouseleave',function(evt){
						this.options.mouseleave(evt);
						this.start();
					}.bindAsEventListener(this));
				}
			}.bind(this));
		}
		['next','back','stop','start'].each(function(item) {
			var action = function(evt) {
				evt.stop();
				this[item]();
			}.bindAsEventListener(this)
			$$(this.options[item]).each(function(item) {
				item.observe('click',action);
			});
		}.bind(this));
	},
	start: function() {
		this.stop();
		if(this.options.timeout > 0) {
			this.peHandle = new PeriodicalExecuter(function(){this.next();}.bind(this),(this.options.delay));
			this.options.delay = this.options.timeout; // delay used on initial start only
		}
	},
	stop: function() {
		if(this.peHandle!=null) {
			this.peHandle.stop();
		}
	},
	back: function() {
		this.move('back');
	},
	next: function() {
		this.move('next');
	},
	move: function(pos) {
		if( pos=='next') {
			this.nextSlide = this.currentSlide +1;
		} else if ( pos=='back' ) {
			this.nextSlide = this.currentSlide -1;
		} else {
			this.nextSlide = pos;
		}
		if(this.nextSlide < 0) {
			this.nextSlide = this.slides.length-1;
		}
		if(this.nextSlide >= this.slides.length) {
			this.nextSlide = 0;
		}
		this.transition();
	},
	transition: function() {
		if(this.inprogress != true) {
			// Prevent new transition while one is in progress
			this.inprogress = true;
			// Run before callback
			if(this.options.before!=null) { 
				this.options.before(this.slides[this.nextSlide]); 
			}
			// Fade out current slide - Fade in next slide 
			this.slides[this.currentSlide].fade({
				duration: this.options.duration
			});         
			this.slides[this.nextSlide].appear({
				duration: this.options.duration,
				afterFinish:function() {
					this.release();
				}.bind(this)
			});
		}
	},
	release: function() {
		this.inprogress = false;
		// run after callback
		if(this.options.after!=null) { 
			this.options.after(this.slides[this.currentSlide]); 
		}
		// Update current - next slide references
		this.currentSlide = this.nextSlide;
		this.nextSlide    = null;
		// Reset PeriodicalExecuter
		this.start();
	},
	options: {
		containerId:   null,  // id of slide container element
		slide:         null,  // expression for selecting slides (if something other than all children is required) 
		delay:         6.0,   // additional delay (in seconds) for first transition
		timeout:       6.0,   // seconds between slide transitions (0 to disable auto advance) 
		duration:      1.0,   // speed of the transition in seconds
		next:          '[class="nooptyNext"]',  // expression for selecting elements to use as click trigger for next slide 
		back:          '[class="nooptyBack"]',  // expression for selecting elements to use as click trigger for back slide 
		stop:          '[class="nooptyStop"]',  // expression for selecting elements to use as click trigger for stop transitions
		start:         '[class="nooptyStart"]', // expression for selecting elements to use as click trigger for start transitions
		before:        null,  // transition callback (scope set to element to be shown) 
		after:         null,  // transition callback (scope set to element that was shown) 
		mouseenter:    null,  // mouseenter callback
		mouseleave:    null,  // mouseleave callback
		hover:         0,     // true to enable "pause on hover" 
		shuffle:       0,     // randomize our array of slides
		primary:       0      // load slides with attribute "primary"="true" by default
	},
	version: function() {
		return '1.0';
	}
});

var NooptyScaler = Class.create({	
	vp: null,
	imgs: [],
	initialize: function(args) {
		// update default options
		var h = $H(args);
		h.each(function(item) {
			if( typeof(this.options[item.key]) != 'undefined' ) {
				this.options[item.key] = item.value ;
			}
		}.bind(this));
		// set slide container element
		if(this.options.containerId!=null && this.options.image!=null) {
			var images = $(this.options.containerId).select(this.options.image);
		} else {
			var images = $$(this.options.image);
		}
		images.each(function(image,idx) {
			this.imgs.push({ 
				ele: image, 
				width: image.getWidth(), 
				height: image.getHeight(), 
				ratio: image.getWidth()/image.getHeight() 
			});
			if(!this.options.rightclick) {
				image.oncontextmenu = function(){return false;}; 
			}
		}.bind(this));
		if(this.options.coverId!=null && !this.options.rightclick) {
			$(this.options.coverId).oncontextmenu = function(){return false;};
		}
		this.update();
	},
	update_vp: function() {
		this.vp = $(this.options.containerId).getDimensions();
		this.vp.ratio = this.vp.width/this.vp.height;
	},
	update: function() {
		this.update_vp();
		this.imgs.each(function(obj) {
			this.resize(obj);
		}.bind(this));
	},
	resize: function(obj) {
		var w,h,t=0,l=0;
		if( this.vp.ratio == obj.ratio) {
			w = this.vp.width;
			h = this.vp.height;
		} else if( this.vp.ratio > obj.ratio) { // window more horizontal than image
			w = this.vp.width;
			h = Math.abs((w*obj.height)/obj.width);
			t = Math.abs((h - this.vp.height)/2);
		} else { //  this.vp.ratio < obj.ratio // window more vertical than image
			h = this.vp.height;
			w = Math.abs((h*obj.width)/obj.height);
			l = Math.abs((w-this.vp.width)/2);
		}
		obj.ele.setStyle({'width':w+'px',
		              'height':h+'px',
		              'left':-l+'px',
		              'top':-t+'px'});
	},
	options: {
		containerId:   null,  // id of slide container element
		coverId:       null,  // id of slide cover element
		image:         null,  // expression for selecting slides (if something other than all children is required) 
		rightclick:    true  // disable right click on image
	},
	version: function() {
		return '1.0';
	}
});

 Array.prototype.shuffle = function(deep) {
	var i = this.length, j, t;
	while( i ) {
		j = Math.floor( ( i-- ) * Math.random() );
		t = deep && typeof this[i].shuffle!=='undefined' ? this[i].shuffle() : this[i];
		this[i] = this[j];
		this[j] = t;
	}
	return this;
};
