/*
	Gallery Component
	
	A very simple component that manages integration between slideshow, slides,
	and controller.
*/

var Azexis = Azexis || {};

(function($) {

	Azexis.gallery = function(controller, slides, slideshow){
		var pub = Azexis.events();
		
		function onChange(id){
			slides.select(id);
			controller.select(id);
		};
		
		function changeImage(e){
			slides.select(e.id);
			slideshow.moveTo(e);
		};
		
		// Add event listeners.
		controller.bind('onChange', function(e){changeImage(e);});
		
		pub.select = function(id){
			controller.select(id);
		};
		
		return pub;
	};

})(jQuery);


/*
	Azexis Controller
	
	Usage:
		Call controller passing in the element (any valid jQuery selector) that
		you want to make controllable. Eg:
		
		Azexis.controller("#myid");
		
		This will return a controller object to interact with.
		
		Any direct children will be turned into the items in the controller,
		with the exception that any with the class "arrow" are ignored and
		assumed to be the previous and next buttons. Adding the classes
		"previous" and "next" will enable this functionality automatically.
		
		Example HTML:
		
		<div id="myid">
			<div class="arrow previous">Prev</div>
			<div>item 1</div>
			<div>item 2</div>
			<div class="arrow next">Next</div>
		</div>
		
	Events:
		onChange:
			Called when an item is selected by any means.
			
*/

var Azexis = Azexis || {};

(function($) {

	Azexis.controller = function(el){
		var pub = Azexis.events();
		var items = $(el).children().not(".arrow");
		var arrows = $(el).children().filter(".arrow");
		var currentItem = 0;
		
		function selectItem(i){
			currentItem = i.mod(items.length);
			$(items[i]).addClass("active").siblings().removeClass("active");
			pub.trigger("onChange", {type: "onChange", id: currentItem, el: items.get(i)});
		};
		
		
		// Set up event handlers.
		items.click(function(e) {
			e.preventDefault();
			selectItem(items.index(this));
		});
		arrows.filter(".previous").click(function(e) {
			selectItem(currentItem-1);
		});
		arrows.filter(".next").click(function(e) {
			selectItem(currentItem+1)
		});
		
		// Public interface
		pub.select = function(id){
			selectItem(id);
		};
		
		return pub;
	};

})(jQuery);


var Azexis = Azexis || {};

(function($) {
	Azexis.slideshow = function(banner, images, options) {
	/*
		Variables
		---------
	*/
		var banner = $(banner);
		var self = Azexis.events();
		var springDuration = 500; // Spring a partially completed fade to completion.
		var images = images;
		var cachedImages = [true];
		var failedInARow = 0;
		// Actually mid-fade, which is never stopped.
		var animating = false;
		// Don't start any new fades automatically, but user interaction can still
		// force a single fade.
		var paused = false;
		var forceSingle = false;
		var lastTime = new Date;
		
		Azexis.slideshow.defaults = {
			autoPlay: true,
			imagesDir: "",
			duration: 2500,
			userDuration: 1000,
			wait: 10000,
			width: banner.innerWidth(),
			height: banner.innerHeight(),
			backgroundPosition: "left top"
		};
		
		var options = $.extend({}, Azexis.slideshow.defaults, options);
		
		// play automatically?
		paused = !options.autoPlay;
		
		var fader = $("<div>").css({
			position: "absolute",
			'z-index':1,
			top: 0,
			left: 0,
			width: options.width,
			height: options.height,
			backgroundRepeat: "no-repeat",
			backgroundPosition: options.backgroundPosition
		});
		
		// Current image is the index of the image that is fully loaded and moved to
		// the background div.
		var nxt = 1;
		
	/*
		Methods
		---------
	*/
		function mod(a,b) { var n = a%b; return n < 0 ? n+b : n; }
		function currentImage() { if(images) return mod(nxt-1,images.length); }
		function nextImage() { if(images) return mod(nxt,images.length); }
		function advanceImage() { nxt += 1; }
	
		// User manually changes to another slide.
		function changeNext(n) {
			nxt = n;
			
			// Don't interrupt in-progress animations, but switch immediately if we can.
			if (!animating) {
				resetFader();
			} else {
				// I don't know what these did but they look like there were left over from mootools
				// but, everytime i remove them something stops working even though they throw and error
				//fx.stop();
				//fx.setOptions({duration: springDuration});
				//fx.start(1);
				//resetFader();
			}
			
			// User interation always force a single move even if the animation is paused.
			forceSingle = true;
			eventHandler();
		}
		
		function imageToCSS(n) {
			return "url(" + options.imagesDir + images[n] + ")";
		}
		
		function loadNextImage() {
			var img = new Image;
			
			// Store the current imageCache and number in a closure. If they change
			// during the time it takes to load, the next cache won't get the incorrect
			// values written to it.
			img.onload = (function(cache, n) {
				return function() {
					failedInARow = 0;
					fader.css("background-image", imageToCSS(n));
					cache[n] = true;
					eventHandler();
				}
			})(cachedImages, nextImage());
			
			img.onerror = function() {
				// Can't load the image, just try the next.
				if (failedInARow > 10) {
					// Don't keep looking forever.
					return;
				}
				failedInARow++;
				advanceImage();
				resetFader();
			}
			
			// Start load process.
			if(images) {
				img.src = options.imagesDir + images[nextImage()];
			}
		}
		
		function updateCurrentImage() {
			$(banner).css("background-image", fader.css("background-image"));
		}
		
		function resetFader() {
			fader.css("opacity", 0);
			loadNextImage();
		}
		
		function eventHandler() {
			
			if (animating) {
				return;
			}
			
			if (!forceSingle && ((new Date) - lastTime) < options.wait) {
				// Come back when the time is right.
				setTimeout(eventHandler, options.wait - ((new Date) - lastTime));
				return;
			}
			
			if (!cachedImages[nextImage()]) {
				// Not cached yet, the event handler will be called when the cache is
				// complete.
				return;
			}
			
			if (paused && !forceSingle) { return; }
			
			self.trigger('onBeforeImageChange', { 
				type: 'onBeforeImageChange',
				imageId: currentImage(),
				src: images[currentImage()]
			});
			
			// check again to check if a listener paused 
			// the slideshow before the image was shown
			if (paused && !forceSingle) { return; }
			
			
			var fadeDuration = options.duration;
			if (forceSingle) {
				forceSingle = false;
				fadeDuration = options.userDuration;
			} 
			self.trigger('onImageChange', { 
				type: 'onImageChange',
				imageId: nextImage(),
				src: images[nextImage()]
			});
			
			fader.animate({opacity: 1}, fadeDuration, "linear", function() {
				lastTime = new Date;
				updateCurrentImage();
				
				// Delay added to prevent flicker during image swap.
				setTimeout(function() {
					animating = false;
					resetFader();
					eventHandler();
					self.trigger('onAfterImageChange', { 
						type: 'onAfterImageChange',
						imageId: currentImage(),
						src: images[currentImage()]
					});
				}, 100);
			});
			animating = true;
			advanceImage();
		}
		
	/*
		Public Methods
		---------------
	*/
		self = $.extend({
			loadImageSequence: function(seq) {
				images = seq;
				cachedImages = [];
				changeNext(0);
			},
			
			pause: function() {
				paused = true;
			},
			
			resume: function() {
				paused = false;
				eventHandler();
			},
			
			play: function(){
				paused = false;
				eventHandler();
			},
			
			moveTo: function(n) {
				changeNext(n);
			},
			
			moveToNext: function() {
				changeNext(currentImage()+1);
			},
			
			moveToPrevious: function() {
				changeNext(currentImage()-1);
			}
		}, self);
		
	/*
		Logic
		------
	*/
		banner.append(fader);
		resetFader();
		eventHandler();
		return self;
	};
})(jQuery);


/*
	Azexis.slides
	--------------
	This is usually used as the thumbnail slides beneath a gallery.
	But, may be used by itself. Generally this will have a next and previous button.
*/
var Azexis = Azexis || {};

(function($) {
	Azexis.slides = function(el, options){
		var pub = Azexis.events();
		var container = el;
		var mask = $('.mask', container);
		var items = 0;
		var slides = null;
		var isAnimating = false;
		var totalWidth = 0;
		var totalHeight = 0;
		
		Azexis.slides.defaults = {
			orientation: 'h',
			slides: '.mask ul',
			slide: '.mask ul li',
			duration: 1500
		};
		
		var options = $.extend({}, Azexis.slides.defaults, options);
		var property = (options.orientation == 'h')?'width':'height';
		var outerProperty = (options.orientation == 'h')?'outerWidth':'outerHeight';
		var positionProperty = (options.orientation == 'h')?'left':'top';
		
		function setup(){
			mask.height(thumbnailHeight);
			var thumbnailHeight = $('.thumbnails li:first', container).outerHeight(true);
			mask.css({
						overflow: 'hidden',
						width: mask.width(),
						height: thumbnailHeight,
						position: 'relative',
						top:0,
						left:0
					 });
			slides = $(options.slides);
			$(options.slide).each(function(){
				totalWidth += ($(this).outerWidth(true));
				++items;
			});
			totalHeight = slides.outerHeight();
			if(options.orientation == 'h'){
				slides.width(totalWidth);
				slides.height(mask.height());
			} else {
				slides.height(totalHeight);
				slides.width(mask.width());
			}
			$('.next', container).bind('click', function(e){ next(); return false; });
			$('.previous', container).bind('click', function(e){ previous(); return false; });
			updateButtons();
		};
		
		function next(){
			if(!isAnimating && (slides[property]()>mask[property]())){
				// calculate the position we need
				var position = slides.position();
				var marker = (mask[property]()-position[positionProperty]);
				var tally = 0;
				if((marker+mask[property]())>(slides[property]())){
					tally = (slides[property]() - mask[property]());
				} else {
					$(options.slide).each(function(){
						var dimension = $(this)[outerProperty](true);
						if((tally + dimension) <= marker){
							tally += dimension;
						} else {
							return false
						}
					});
				}
				isAnimating=true;
				var obj = {};
				obj[positionProperty] = (0-tally);
				slides.animate(obj, options.duration, function(e){animationComplete();});
			}
		};
		
		function previous(){
			if(!isAnimating && (slides[property]()>mask[property]())){
				var position = slides.position();
				var marker = (position[positionProperty]+mask[property]());
				var tally = 0;
				$(options.slide).each(function(){
					tally += $(this)[outerProperty](true);
					if(tally >= (0-position[positionProperty])){
						marker = 0-(tally - mask[property]());
						return false;
					}
				});
				tally = (marker<0)?marker:0;
				isAnimating = true;
				var obj = {};
				obj[positionProperty] = tally;
				slides.animate(obj, options.duration, function(e){animationComplete();});
			}
		};
		
		function scrollToItem(id){
			if(!isAnimating && (slides[property]()>mask[property]())){
				var tally = 0;
				jQuery.each($(options.slide), function(i, item){
					if(i == id){
						return false;
					} else {
						tally += $(item)[outerProperty](true);
					}
				});
				if((tally + mask[property]())>slides[property]()){
					tally = slides[property]()-mask[property]();
				}
				isAnimating = true;
				var obj={};
				obj[positionProperty] = (0-tally);
				slides.animate(obj, options.duration, function(e){animationComplete();});
			}
		};
		
		function updateButtons(){
			$('.next', container).removeClass('disabled');
			$('.previous', container).removeClass('disabled');
			if(slides[property]() <= mask[property]()){
				$('.previous', container).addClass('disabled');
				$('.next', container).addClass('disabled');
			}
			if(slides.position()[positionProperty] == 0){
				$('.previous', container).addClass('disabled');
			} else if((0-slides.position()[positionProperty])+mask[property]() == slides[property]()){
				$('.next', container).addClass('disabled');
			}
		};
		
		function animationComplete(e){
			isAnimating = false;
			updateButtons();
			var obj = {
				'type': 'onAnimationComplete',
				'visible': getVisibleItems(),
				'current': getCurrent()
			};
			pub.trigger('onAnimationComplete', obj);
		};
		
		function getVisibleItems(){
			var minPosition = (0-slides.position()[positionProperty]);
			var maxPosition = minPosition + mask[property]();
			var items = [];
			jQuery.each($(options.slide), function(i, item){
				item = $(item);
				if((item.position()[positionProperty] >= minPosition) && (item.position()[positionProperty] < maxPosition)){
					items.push(i);
				}
			});
			return items;
		};
		
		function getCurrent(){
			var current = false;
			jQuery.each($(options.slide), function(i, item){
				item = $(item);
				if(item.hasClass('active')){
					current = i;
					return false;
				}
			});
			return current;
		};
		
		function selectItem(id){
			jQuery.each($(options.slide), function(i, item){
				item = $(item);
				item.removeClass('active');
				if(i == id) item.addClass('active');
			});
			var isVisible = (jQuery.inArray(id, getVisibleItems())>=0);
			if(!isVisible) scrollToItem(id);
		};
		
		pub.moveTo = function(id){
			scrollToItem(id);
		};
		
		pub.select = function(id){
			selectItem(id);
		};
		
		setup();
		return pub;
	};
	
})(jQuery);


/*
	Slimbox v2.02 - The ultimate lightweight Lightbox clone for jQuery
	(c) 2007-2009 Christophe Beyls <http://www.digitalia.be>
	MIT-style license.
*/
(function(w){var E=w(window),u,g,F=-1,o,x,D,v,y,L,s,n=!window.XMLHttpRequest,e=window.opera&&(document.compatMode=="CSS1Compat")&&(w.browser.version>=9.3),m=document.documentElement,l={},t=new Image(),J=new Image(),H,a,h,q,I,d,G,c,A,K;w(function(){w("body").append(w([H=w('<div id="lbOverlay" />')[0],a=w('<div id="lbCenter" />')[0],G=w('<div id="lbBottomContainer" />')[0]]).css("display","none"));h=w('<div id="lbImage" />').appendTo(a).append(q=w('<div style="position: relative;" />').append([I=w('<a id="lbPrevLink" href="#" />').click(B)[0],d=w('<a id="lbNextLink" href="#" />').click(f)[0]])[0])[0];c=w('<div id="lbBottom" />').appendTo(G).append([w('<a id="lbCloseLink" href="#" />').add(H).click(C)[0],A=w('<div id="lbCaption" />')[0],K=w('<div id="lbNumber" />')[0],w('<div style="clear: both;" />')[0]])[0]});w.slimbox=function(O,N,M){u=w.extend({loop:false,overlayOpacity:0.8,overlayFadeDuration:400,resizeDuration:400,resizeEasing:"swing",initialWidth:250,initialHeight:250,imageFadeDuration:400,captionAnimationDuration:400,counterText:"Image {x} of {y}",closeKeys:[27,88,67],previousKeys:[37,80],nextKeys:[39,78]},M);if(typeof O=="string"){O=[[O,N]];N=0}y=E.scrollTop()+((e?m.clientHeight:E.height())/2);L=u.initialWidth;s=u.initialHeight;w(a).css({top:Math.max(0,y-(s/2)),width:L,height:s,marginLeft:-L/2}).show();v=n||(H.currentStyle&&(H.currentStyle.position!="fixed"));if(v){H.style.position="absolute"}w(H).css("opacity",u.overlayOpacity).fadeIn(u.overlayFadeDuration);z();k(1);g=O;u.loop=u.loop&&(g.length>1);return b(N)};w.fn.slimbox=function(M,P,O){P=P||function(Q){return[Q.href,Q.title]};O=O||function(){return true};var N=this;return N.unbind("click").click(function(){var S=this,U=0,T,Q=0,R;T=w.grep(N,function(W,V){return O.call(S,W,V)});for(R=T.length;Q<R;++Q){if(T[Q]==S){U=Q}T[Q]=P(T[Q],Q)}return w.slimbox(T,U,M)})};function z(){var N=E.scrollLeft(),M=e?m.clientWidth:E.width();w([a,G]).css("left",N+(M/2));if(v){w(H).css({left:N,top:E.scrollTop(),width:M,height:E.height()})}}function k(M){w("object").add(n?"select":"embed").each(function(O,P){if(M){w.data(P,"slimbox",P.style.visibility)}P.style.visibility=M?"hidden":w.data(P,"slimbox")});var N=M?"bind":"unbind";E[N]("scroll resize",z);w(document)[N]("keydown",p)}function p(O){var N=O.keyCode,M=w.inArray;return(M(N,u.closeKeys)>=0)?C():(M(N,u.nextKeys)>=0)?f():(M(N,u.previousKeys)>=0)?B():false}function B(){return b(x)}function f(){return b(D)}function b(M){if(M>=0){F=M;o=g[F][0];x=(F||(u.loop?g.length:0))-1;D=((F+1)%g.length)||(u.loop?0:-1);r();a.className="lbLoading";l=new Image();l.onload=j;l.src=o}return false}function j(){a.className="";w(h).css({backgroundImage:"url("+o+")",visibility:"hidden",display:""});w(q).width(l.width);w([q,I,d]).height(l.height);w(A).html(g[F][1]||"");w(K).html((((g.length>1)&&u.counterText)||"").replace(/{x}/,F+1).replace(/{y}/,g.length));if(x>=0){t.src=g[x][0]}if(D>=0){J.src=g[D][0]}L=h.offsetWidth;s=h.offsetHeight;var M=Math.max(0,y-(s/2));if(a.offsetHeight!=s){w(a).animate({height:s,top:M},u.resizeDuration,u.resizeEasing)}if(a.offsetWidth!=L){w(a).animate({width:L,marginLeft:-L/2},u.resizeDuration,u.resizeEasing)}w(a).queue(function(){w(G).css({width:L,top:M+s,marginLeft:-L/2,visibility:"hidden",display:""});w(h).css({display:"none",visibility:"",opacity:""}).fadeIn(u.imageFadeDuration,i)})}function i(){if(x>=0){w(I).show()}if(D>=0){w(d).show()}w(c).css("marginTop",-c.offsetHeight).animate({marginTop:0},u.captionAnimationDuration);G.style.visibility=""}function r(){l.onload=null;l.src=t.src=J.src=o;w([a,h,c]).stop(true);w([I,d,h,G]).hide()}function C(){if(F>=0){r();F=x=D=-1;w(a).hide();w(H).stop().fadeOut(u.overlayFadeDuration,k)}return false}})(jQuery);

// AUTOLOAD CODE BLOCK (MAY BE CHANGED OR REMOVED)
jQuery(function($) {
	$("a[rel^='lightbox']").slimbox({/* Put custom options here */}, null, function(el) {
		return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel));
	});
});

