/*******************************************************
Author:			Tim Miller
Date:			7/16/2009
Filename:		jquery.contentSelector.js

***** THIS PLUGIN REQUIRES THE JQUERY LIBRARY *****
***** Some transition effects require the jQuery UI (slideLR) *****

***** 
Required reading:

For some of the transition effects to work properly the children elements must be POSITIONED ABSOLUTELY. When the 
contentSelector is created it sets the position property of the parent element to "RELATIVE" and the position property 
of each of the chilren to "ABSOLUTE." The height of the parent object is set to the height of the tallest child element.
*****
						
The "params" is a single object that can have the following properties:

prop. name        | description																	| default
---------------------------------------------------------------------------------------------------------------
*jQSelector       | The jQuery selector for the element containing the children to              | NONE (REQUIRED)
					randomize/flip through.	
childJQSelector   | The jQuery selector for children.											| div
isRand            | If the script should randomly pick the first child to show. boolean			| true
defaultItemIndex  | If isRand is false you can set the first item you would like to show.		| 1
transition        | Type of transition between objects. Options are: none, fade, slide.			| none
	tSlideDir     | Only applicable to the slide transition. Options are: left, right, up, down.| left
tDuration         | Transition duration (seconds).												| 0.5
tDelay            | Transition delay. Default depends on the transition. Enables crossfading...	| null
tMin              | Only applicable to the fade transition. Transition min.						| 0.0
tMax              | Only applicable to the fade transition. Transition max.						| 1.0
slideShow         | Auto change. boolean														| false
ssTimer           | Slideshow timer (seconds).													| 5

* - Required parameter.
	
This can be called at any time in the body of the document after the parent element has been closed 
or onload of the window.

Examples:
	var inFocusStories = new contentSelector({
		jQSelector :	"div#inFocusContainer"
	});
OR
	var imgRandom = new contentSelector({
		jQSelector			:	"div#inFocusContainer2",
		childJQSelector		:	"img",
		isRand				:	false,
		defaultItemIndex	:	4
	});
*******************************************************/

//Constructor
function contentSelector(params){
	function param_default(pname, def){
		if(typeof params[pname] == "undefined") params[pname] = def;
		return params[pname];
	}
	
	this.jQSelector = param_default("jQSelector", null);
	this.childJQSelector = param_default("childJQSelector", "div");
	this.isRand = param_default("isRand", true);
	this.defaultItemIndex = param_default("defaultItemIndex", 1);
	this.transition = param_default("transition", "none").toLowerCase();
	this.tSlideDir = param_default("tSlideDir", "left").toLowerCase();
	this.tDuration = param_default("tDuration", 0.5);
	this.tDelay = param_default("tDelay", null);
	this.tMin = param_default("tMin", 0.0);
	this.tMax = param_default("tMax", 1.0);
	this.slideShow = param_default("slideShow", false);
	this.ssTimer = param_default("ssTimer", 5);
	
	if(this.jQSelector == null){
		alert("New contentSelector object could not be created. You must specify the jQSelector variable.");
		return;
	}
	
	this.firstLoad = true;
	this.numItems = 0;
	this.currentItemIndex = 0;
	this.currentItemObj;
	this.targetParent = jQuery(this.jQSelector);
	this.Rand = contentSelector.Rand;
	this.nextItem = contentSelector.nextItem;
	this.previousItem = contentSelector.previousItem;
	this.setupUpdateInterval = contentSelector.setupUpdateInterval;
	this.clearUpdateInterval = contentSelector.clearUpdateInterval;
	this.startSlideshow = contentSelector.startSlideshow;
	this.stopSlideshow = contentSelector.stopSlideshow;
	this.ssInterval = null;
	this.allowControls = true;
	this.tSlideOpDir;
	this.tSlideDelay;
	
	if(this.transition == "fade"){
		if(this.tDelay == null) this.tDelay = this.tDuration;
	}
	else if(this.transition == "slide"){
		switch(this.tSlideDir){
			case "left":
				this.tSlideOpDir = "right";
				if(this.tDelay == null) this.tDelay = 0.1;
				break;
			case "right":
				this.tSlideOpDir = "left";
				if(this.tDelay == null) this.tDelay = 0.1;
				break;
			case "up":
				this.tSlideOpDir = "down";
				if(this.tDelay == null) this.tDelay = 0.45;
				break;
			case "down":
				this.tSlideOpDir = "up";
				if(this.tDelay == null) this.tDelay = 0.45;
				break;
		}
	}
	
	var context = this;
	var parentHeight = 0;
	this.targetParent.children(this.childJQSelector).each(function(){
		var childObj = $(this);
		context.numItems++;
		if(childObj.attr("id") == ""){
			childObj.attr("id", "CS_"+context.targetParent.attr("id")+"_"+context.numItems);
		}
		if($(this).outerHeight(true) > parentHeight) parentHeight = $(this).outerHeight(true);
		childObj.css({
			"position": "absolute",
			"display": "none",
			"opacity": function(){
				return (context.transition == "fade")?context.tMin:childObj.css("opacity")
			}
		});
	});
	
	this.targetParent.css({
		"position": "relative",
		"height": parentHeight+"px"
	});
	
	if(this.isRand){
		this.Rand();
	}else{
		this.nextItem(this.defaultItemIndex);
	}
}

//Function to randomly select a child element inside the containing object to display.
contentSelector.Rand = function(){
	var randNum = Math.ceil(Math.random() * this.numItems);
	this.currentItemIndex = randNum-1;
	
	this.nextItem();
}

//Function to flip through the child elements inside a containing object in order.
contentSelector.nextItem = function(index){
	if(!this.allowControls) return;
	this.allowControls = false;
	
	if(typeof index != "undefined" && index == this.currentItemIndex) return;
	
	var index = (typeof index == "undefined")?this.currentItemIndex:index-1;
	var nextNum = (index >= this.numItems)?1:index+1;
	var nextItemObj;
	
	if(this.slideShow) this.clearUpdateInterval();
	
	this.currentItemIndex = nextNum;
	
	var context = this;
	var foundItems = 0;
	this.targetParent.children(this.childJQSelector).each(function(){
		var childObj = $(this);
		foundItems++;
		if(foundItems == context.currentItemIndex){
			nextItemObj = childObj;
		}
	});
	
	if(this.firstLoad){
		nextItemObj.css({
			"display": "block",
			"opacity": this.tMax
		});
		this.firstLoad = false;
		this.currentItemObj = nextItemObj;
		if(this.slideShow) this.setupUpdateInterval();
		this.allowControls = true;
	}else{
		if(this.transition == "none"){
			this.currentItemObj.css("display", "none");
			nextItemObj.css("display", "block");
			this.currentItemObj = nextItemObj;
			if(this.slideShow) this.setupUpdateInterval();
			this.allowControls = true;
		}
		else if(this.transition == "fade"){
			this.currentItemObj.fadeTo(context.tDuration*1000, context.tMin, function(){
				context.currentItemObj.css("display", "none");
				context.currentItemObj = nextItemObj;
			});
			nextItemObj.delay(context.tDelay*1000).css("display", "block").fadeTo(context.tDuration*1000, context.tMax, function(){
				if(context.slideShow) context.setupUpdateInterval();
				context.allowControls = true;
			});
		}
		else if(this.transition == "slide"){
			this.currentItemObj.hide("slide", { direction: context.tSlideDir }, context.tDuration*1000);
			nextItemObj.delay(context.tDelay*1000).show("slide", { direction: context.tSlideOpDir }, context.tDuration*1000, function(){
				if(context.slideShow) context.setupUpdateInterval();
				context.allowControls = true;
			});
			context.currentItemObj = nextItemObj;
		}
	}
}

//Function to flip through the child elements inside a containing object in reverse-order.
contentSelector.previousItem = function(index){
	if(!this.allowControls) return;
	this.allowControls = false;

	var index = (typeof index == "undefined")?this.currentItemIndex:index-1;
	var prevNum = (index <= 1)?this.numItems:index-1;
	var previousItemObj;
	
	if(this.slideShow) this.clearUpdateInterval();
	
	this.currentItemIndex = prevNum;
	
	var context = this;
	var foundItems = 0;
	this.targetParent.children(this.childJQSelector).each(function(){
		var childObj = $(this);
		foundItems++;
		if(foundItems == context.currentItemIndex){
			previousItemObj = childObj;
		}
	});
	
	if(this.firstLoad){
		previousItemObj.css({
			"display": "block",
			"opacity": this.tMax
		});
		this.firstLoad = false;
		this.currentItemObj = previousItemObj;
		if(this.slideShow) this.setupUpdateInterval();
		this.allowControls = true;
	}else{
		if(this.transition == "none"){
			this.currentItemObj.css("display", "none");
			previousItemObj.css("display", "block");
			this.currentItemObj = previousItemObj;
			if(context.slideShow) context.setupUpdateInterval();
			context.allowControls = true;
		}
		else if(this.transition == "fade"){
			this.currentItemObj.fadeTo(context.tDuration*1000, context.tMin, function(){
				context.currentItemObj.css("display", "none");
				context.currentItemObj = previousItemObj;
			});
			previousItemObj.delay(context.tDelay*1000).css("display", "block").fadeTo(context.tDuration*1000, context.tMax, function(){
				if(context.slideShow) context.setupUpdateInterval();
				context.allowControls = true;
			});
		}
		else if(this.transition == "slide"){
			this.currentItemObj.hide("slide", { direction: context.tSlideOpDir }, context.tDuration*1000);
			previousItemObj.delay(context.tDelay*1000).show("slide", { direction: context.tSlideDir }, context.tDuration*1000, function(){
				if(context.slideShow) context.setupUpdateInterval(); 
				context.allowControls = true;
			});
			context.currentItemObj = previousItemObj;
		}
	}
}

//Slideshow functions
contentSelector.setupUpdateInterval = function(){
	var context = this;
	this.ssInterval = window.setInterval(function(){ context.nextItem() }, this.ssTimer*1000);
}
contentSelector.clearUpdateInterval = function(){
	window.clearInterval(this.ssInterval);
	this.ssInterval = null;
}
contentSelector.startSlideshow = function(){
	this.slideShow = true;
	this.setupUpdateInterval();
}
contentSelector.stopSlideshow = function(){
	this.slideShow = false;
	this.clearUpdateInterval();
}
