String.prototype.trim = function () {
	return this.replace(/^\s+|\s+$/, "");
};


/*
*	BubbleBox is referenced outside of this script - must be set in global scope
*/
function CRB_BubbleBox(callbacks) {
	this.callbacks = callbacks;
	this.active = false;

	this.init = function () {
		// create necessary HTML elements
		if (!$("#bubble-box-overlay").length) {
			$("body").append("<div id=\"bubble-box-overlay\"></div>");
		}
		if (!$("#bubble-box").length) {
			$("body").append(
				"<div id=\"bubble-box\">\n" +
				"\t<div class=\"bubbles\"></div>\n" +
				"\t<div class=\"content\">\n" +
				"\t\t<a class=\"close\" href=\"\">Close</a>\n" +
				"\t\t<div class=\"content-box cfx\">\n" +
				"\t\t</div>\n" +
				"\t</div>\n" +
				"</div>\n"
			);
		}

		// bind close events
		var bubbleBox = this;
//		$("#bubble-box-overlay").click(function () {
//			bubbleBox.close();
//		});
		$("#bubble-box .close").click(function () {
			bubbleBox.close();
			return false;
		});
	};

	this.close = function () {
		if (!this.active) {
			return false;
		}

		$("#bubble-box").hide();
		$("#bubble-box-overlay").fadeOut(300, function () {
			// unbind click event from overlay
			$(this).unbind("click");
		});

		this.active = false;

		if (this.callbacks.close) {
			this.callbacks.close();
		}
	};

	this.open = function () {
		var self = this,
			height = $("#bubble-box").outerHeight();

		this.active = true;

		// set margins to center on screen
		if (height > $(window).height()) {
			// box won't fit on screen all at once. Remove fixed positioning.
			$("#bubble-box").css({
				position : "absolute",
				"margin-top" : (($(document).height() - height) / 2)
			});
		} else {
			$("#bubble-box").css({
				position : "fixed",
				"margin-top" : (-(height / 2))
			});
		}

		// display the BubbleBox
		$("#bubble-box-overlay").fadeIn(300, function () {
			// bind click event to overlay
			$("#bubble-box-overlay").click(function () {
				self.close();
			});

			$("#bubble-box").show();
		});

		if (this.callbacks.open) {
			this.callbacks.open();
		}
	};

	this.setContent = function (html) {
		$("#bubble-box .content .content-box").html(html);
	};
/*
	this.getContent = function() {
		return $("#bubble-box .content .content-box").html();
	}

	this.clearContent = function() {
		$("#bubble-box .content .content-box").html("");
	}

	this.appendContent = function(html) {
		$("#bubble-box .content .content-box").append(html);
	}

	this.prependContent = function(html) {
		$("#bubble-box .contnet .content-box").prepend(html);
	}
*/
}

(function () {
	"use strict";

	String.prototype.ucFirst = function () {
		return this.replace(/^\w/, function (firstChar) {
			return firstChar.toUpperCase();
		});
	};

	function CRB_Slider(params) {
		this.init = function () {
			var self = this,
				btns = [];

			// slider objects/controls
			this.direction = params.direction || "horizontal";
			this.btnPrev = params.btnPrev || false;
			this.btnNext = params.btnNext || false;
			this.btnGoTo = params.btnGoTo || false;
			this.viewbox = params.viewbox;
			this.panes = params.panes;

			// create the slide, and move the panes into it
			$(this.viewbox).prepend("<div class=\"slide\"></div>");
			this.slide = this.viewbox + " .slide";
			$(this.slide).append($(this.panes));

			// duplicate the first pane at the end of the group (Needed to create animation that doesn't 'rewind')
			$(this.slide).append($(this.panes).eq(0).clone());

			// set required CSS values to allow the animation
			$(this.viewbox).css({"position" : "relative"});
			$(this.slide).css({
				position : "relative",
				width : "999999px"
			});

			// calculate initial states/attributes
			if (this.direction == "vertical") {
				this.curPos = $(this.slide).position().top;					// the current y co-ordinate/CSS top value of the slider
			} else {
				this.curPos = $(this.slide).position().left;				// the current x co-ordinate/CSS left value of the slider
			}
			this.startPos = this.curPos;									// allow an initial offset other than 0
			this.curGroup = params.group || 1;								// the current group being viewed
			this.interval = params.interval || 300;							// the time (in milliseconds) for the duration of the animation
			this.groups = $(this.panes).length;								// the number of groups or panes to slide through
//			this.viewBoxWidth = $(this.viewbox).width();
//			this.viewBoxHeight = $(this.viewbox).height();
			this.animateWidth = $(this.panes).outerWidth();					// the horizontal distance to slide when changing panes
			this.animateHeight = $(this.panes).outerHeight();				// the vertical distance to slide when changing panes

			// BIND EVENTS
			$(this.btnPrev).mousedown(function () {
				self.retreat();
			});
			$(this.btnNext).mousedown(function () {
				self.advance();
			});
			$(this.btnGoTo.btn).mousedown(function () {
				self.goTo($(this).find(self.btnGoTo.paneID).val());
			});

			if (this.btnPrev) {
				btns.push(this.btnPrev);
			}
			if (this.btnNext) {
				btns.push(this.btnNext);
			}
			if (this.btnGoTo && this.btnGoTo.btn) {
				btns.push(this.btnGoTo.btn);
			}
			$(btns.join(", ")).click(function () {
				return false;
			});

			if (this.groups > 1) {
				$(this.btnNext).addClass("active");
			}
		};

/*
		this.resetSlider = function() {
			this.curPos = this.startPos;
			this.curGroup = 1;
			this.groups = $(params.pane).length;
	
			// BIND EVENTS
			var self = this;
			$(this.btnPrev).mousedown(function(){self.retreat();});
			$(this.btnNext).mousedown(function(){self.advance();});
			$(this.btnGoTo.btn).mousedown(function(){self.goTo($(this).find(self.btnGoTo.paneID).val());});
			
			var btns = [];
			if (this.btnPrev) {btns.push(this.btnPrev);}
			if (this.btnNext) {btns.push(this.btnNext);}
			if (this.btnGoTo && this.btnGoTo.btn) {btns.push(this.btnGoTo.btn);}
			$(btns.join(", ")).click(function(){return false;});
	
			$(this.btnPrev+", "+this.btnNext).removeClass("active");
			if(this.groups > 1){
				$(this.btnNext).addClass("active");
			}
		};
*/

		// Move the slider forward one pane
		this.advance = function () {
			var self = this,
				params = {},
				destination = 0;

			if (this.direction == "vertical") {
				destination = this.curPos -= this.animateHeight;
				params.top = destination;
			} else {
				destination = this.curPos -= this.animateWidth;
				params.left = destination;
			}

			$(this.slide).stop(true, true);

			if (this.callbackBeforeAdvance) {
				this.callbackBeforeAdvance();
			}

			this.curGroup ++;
			$(this.slide).animate(params, this.interval, function () {
				self.curPos = destination;
/*
				if (self.curGroup == self.groups) {
					$(self.btnNext).removeClass("active");
				}
				if (self.groups > 1) {
					$(self.btnPrev).addClass("active");
				}
*/
				if (self.curGroup >= self.groups) {
					self.rewind();
				}

				// put the active class on the selected button
				$(self.btnGoTo.btn).removeClass("active").eq(self.curGroup - 1).addClass("active");

				if (self.callbackAfterAdvance) {
					self.callbackAfterAdvance();
				}
			});
		};

		this.rewind = function () {
			this.curPos = this.startPos;
			this.curGroup = 1;
			if (this.direction == "vertical") {
				$(this.slide).css({"top" : this.startPos});
			} else {
				$(this.slide).css({"left" : this.startPos});
			}
		};

/*
		// Move the slider backward one pane
		this.retreat = function() {
			if (this.curGroup <= 1) {
				return;
			}
			$(this.slide).stop(true,true);
			
			if (this.callbackBeforeRetreat) {
				this.callbackBeforeRetreat();
			}
			
			this.curGroup--;
			var self = this;
			$(this.slide).animate({"left":this.curPos+this.viewBoxWidth},this.interval,function() {
				self.curPos += self.viewBoxWidth;
				if (self.curGroup == 1) {
					$(self.btnPrev).removeClass("active");
				}
				if (self.groups > 1) {
					$(self.btnNext).addClass("active");
				}
				
				// put the active class on the selected button
				$(self.btnGoTo.btn).removeClass("active").eq(self.curGroup - 1).addClass("active");
				
				if (self.callbackAfterRetreat) {
					self.callbackAfterRetreat();
				}
			});
		};
*/
		// Move the slider to the selected pane
		this.goTo = function (paneID) {
			var params = {},
				destination = 0,
				self = this;

			if (this.curGroup == paneID) {
				return;
			}

			if (this.direction == "vertical") {
				destination = (this.animateHeight * (paneID - 1)) * -1;
				params.top = destination;
			} else {
				destination = (this.animateWidth * (paneID - 1)) * -1;
				params.left = destination;
			}

			$(this.slide).stop(true, true);

			if (this.callbackBeforeGoTo) {
				this.callbackBeforeGoTo();
			}

			this.curGroup = paneID;
			$(this.slide).animate(params, this.interval, function () {
				self.curPos = destination;

				// put the active class on the selected button
				$(self.btnGoTo.btn).removeClass("active").eq(paneID - 1).addClass("active");

				if (self.callbackAfterGoTo) {
					self.callbackAfterGoTo();
				}
			});
		};

		// Callback events
		this.beforeAdvance = function (f) {
			this.callbackBeforeAdvance = f;
		};
		this.afterAdvance = function (f) {
			this.callbackAfterAdvance = f;
		};
		this.beforeRetreat = function (f) {
			this.callbackBeforeRetreat = f;
		};
		this.afterRetreat = function (f) {
			this.callbackAfterRetreat = f;
		};
		this.beforeGoTo = function (f) {
			this.callbackBeforeGoTo = f;
		};
		this.afterGoTo = function (f) {
			this.callbackAfterGoTo = f;
		};

		// put the slider object in play
		this.init();
	}

	var highlights = {
		images : [],
		imagesLoaded : 0,
		slider : false,
		timer : false,
		init : function () {
			var self = this;

			if (!$("#header-highlights .viewbox").length) {
				return false;
			}

			// Instantiate a slider object
			this.slider = new CRB_Slider({
				direction : "vertical",
				btnGoTo : {
					btn : "#header-highlights .pane-selector li a",
					paneID : "[name=\"paneID\"]"
				},
//				btnPrev : "#header-highlights .left",
//				btnNext : "#header-highlights .right",
				panes : "#header-highlights .viewbox .pane",
				viewbox : "#header-highlights .viewbox",
				interval : 999
			});

			// reset the autochange timer if pane selected manually
			this.slider.beforeGoTo(function () {
				window.clearInterval(self.timer);
				self.timer = window.setInterval(self.autoChange, 10000);
			});

			// load images for panes not shown, and start the slider when finished
			this.loadNextImages();
		},
		autoChange : function () {
			highlights.slider.advance();
/*
			// automatically go to the next banner
			var next = parseInt(highlights.slider.curGroup,10) + 1;
			if (next > highlights.slider.groups) {
				next = 1;
			}
			highlights.slider.goTo(next);
*/
		},
		loadNextImages : function () {
			// post load images from other panes
			var self = this;
			$("#header-highlights .viewbox .pane:not(:first-child):not(:last-child)").each(function () {
				var img,
					dims;

				// create a new image object
				self.images.push(new Image());
				img = self.images[self.images.length - 1];

				img.onload = function () {
					self.imagesLoaded ++;
					$(this.customAttributes.node).prepend("<img src=\"" + this.src + "\" alt=\"" + this.customAttributes.alt + "\" width=\"" + this.customAttributes.width + "\" height=\"" + this.customAttributes.height + "\" />");

					if (self.imagesLoaded == self.images.length) {
						// all images have completed loading - start the slider
						self.startSlider();
					}
				};

				img.src = $(this).find("[name=\"src\"]").val();
				dims = $(this).find("[name=\"dims\"]").val().split(",");
				img.customAttributes = {
					node : $(this).find(".l"),
					width : dims[0],
					height : dims[1],
					alt : $(this).find("[name=\"alt\"]").val()
				};
			});
		},
		startSlider : function () {
			// show the pane selector buttons
			$("#header-highlights .pane-selector").fadeIn(1000);

			// Define the timer to auto change the banners
			this.timer = window.setInterval(this.autoChange, 10000);
//			var self = this;
//			$("#header-highlights").mouseover(function() {
//				clearInterval(self.timer);
//			}).mouseout(function() {
//				self.timer = window.setInterval(self.autoChange,5000);
//			});
		}
	};
	highlights.init();

	// --------------------------------------------------------------------------------

	function CRB_ScreenSwitch() {

		this.init = function (params) {
			var self = this;

			// get the objects/information/attributes needed for the screenshot viewer
			this.el = params.el ? $(params.el) : "#screenshots";						// main container div
			if (!this.el.length) {
				return false;
			}
			this.viewbox = params.viewbox ? $(params.viewbox) : $(".viewbox");			// the viewbox that contains the panes of images
			this.controls = params.controls ? $(params.controls) : $(".controls");		// the box containing the switch controls/buttons
			this.loading = params.loading ? $(params.loading) : $(".loading");			// loading graphic
			this.files = params.files.length ? params.files : [];						// array of files
			if (!this.files[0]) {
				return false;
			}

			// create the needed HTML objects based on the files
			this.getHTMLElements();

			// bind events to controls
			this.controls.buttons.mousedown(function () {
				self.change(this.fileIndex);
			});
			this.controls.buttons.click(function () {
				return false;
			});

			// load the first image
			this.loadFirstImage();
		};

		this.getHTMLElements = function () {
			var i;
			// create a view pane and control button to correspond to each file
			for (i in this.files) {
				this.viewbox.append("<div class=\"pane\"></div>");
				this.controls.append("<a class=\"btn\" href=\"\" title=\"Screenshot: " + (parseInt(i, 10) + 1) + "\">View Screenshot</a>");
			}
			this.viewbox.panes = this.viewbox.find(".pane");
			this.viewbox.panes.current = 0;
			this.controls.buttons = this.controls.find(".btn");
			for (i in this.controls.buttons) {
				this.controls.buttons[i].fileIndex = i;
			}
		};

		this.loadFirstImage = function () {
			var self = this,
				firstImg = new Image();

			// show the loading image
			this.loading.show();

			// start loading the first image
			firstImg.onload = function () {
				var img = self.files[0],
					pane = self.viewbox.panes.eq(0);

				// hide loading graphic, hide all panes
				self.loading.hide();
				self.viewbox.panes.hide();

				// create image HTML in the first pane, show pane
				pane.html("<img src=\"" + img.src + "\" alt=\"" + img.alt + "\" width=\"" + img.width + "\" height=\"" + img.height + "\" title=\"" + img.title + "\" />");
				pane.show();

				// set first control button to active, show control buttons
				self.controls.buttons.eq(0).addClass("active");
				self.controls.show();

				// start loading all images
				self.loadAllImages();
			};
			firstImg.src = this.files[0].src;
		};

		this.loadAllImages = function () {
			for (var i in this.files) {
				var self = this,
					file = this.files[i];

				file.image = new Image();

				// store the files index in the image object, so related file information can be retrieved during the onload callback
				file.image.fileIndex = i;
				// store the loaded status so it can be check later
				file.image.loaded = false;

				file.image.onload = function () {
					this.loaded = true;

					// create the image html in the image's respective pane
					var img = self.files[this.fileIndex];
					self.viewbox.panes.eq(this.fileIndex).html("<img src=\"" + img.src + "\" alt=\"" + img.alt + "\" width=\"" + img.width + "\" height=\"" + img.height + "\" title=\"" + img.title + "\" />");

					// if current image being viewed is this image
					if (self.viewbox.panes.current == this.fileIndex) {
						// hide loading graphic, hide all panes
						self.loading.hide();
						self.viewbox.panes.hide();

						// show this pane
						self.viewbox.panes.eq(this.fileIndex).show();
					}
				};
				file.image.src = file.src;
			}
		};

		this.change = function (i) {
			if (this.viewbox.panes.current == i) {
				return false;
			}
			this.viewbox.panes.current = i;
			this.controls.buttons
				.removeClass("active")
				.eq(i).addClass("active");

			this.viewbox.panes.hide();

			if (this.files[i].image.loaded) {
				// if image is loaded, hide loading graphic, show pane
				this.loading.hide();
				this.viewbox.panes.eq(i).show();
			} else {
				// onload callback for image will hide loading graphic and show pane
				// if it is the current one being viewed, so just show loading graphic.
				//show loading graphic
				this.loading.show();
			}
		};
	}

	var fileList = [];
	$("#work-screenshots .file-list li").each(function () {
		fileList.push({
			src : $(this).find("[name=\"src\"]").val(),
			alt : $(this).find("[name=\"alt\"]").val(),
			width : $(this).find("[name=\"width\"]").val(),
			height : $(this).find("[name=\"height\"]").val(),
			title : $(this).find("[name=\"title\"]").val()
		});
	});
	new CRB_ScreenSwitch().init({
		el : "#work-screenshots",
		viewbox : "#work-screenshots .viewbox",
		loading : "#work-screenshots .loading",
		controls : "#work-screenshots .controls",
		files : fileList
	});

	// --------------------------------------------------------------------------------

	var requestProposal = {
		init : function () {
			var self = this;

			if (!$("#header-content .request-proposal").length) {
				return false;
			}

			this.bubbleBox = new CRB_BubbleBox({
				close:this.unload
			});
			this.bubbleBox.init();

			$("#header-content .request-proposal a").click(function () {
				self.load();
				return false;
			});
			$("#request-quote-form").live("submit",function () {
				self.validate();
				return false;
			});
		},
		unload : function () {
		},
		load : function () {
			var html = (
				"<form id=\"request-quote-form\" method=\"get\" action=\"\">\n" +
				"\t<hgroup>\n" +
				"\t\t<h1 class=\"grunge-font\">Request a Proposal</h1>\n" +
				"\t\t<h2>Proposal Form</h2>\n" +
				"\t</hgroup>\n" +
				"\t<div class=\"group cfx\">\n" +
				"\t\t<div class=\"el\">\n" +
				"\t\t\t<label for=\"quote-name\">Name <span class=\"reqd\">(required)</span></label>\n" +
				"\t\t\t<input id=\"quote-name\" type=\"text\" name=\"name\" />\n" +
				"\t\t</div>\n" +
				"\t\t<div class=\"el\">\n" +
				"\t\t\t<label for=\"quote-email\">Email <span class=\"reqd\">(required)</span></label>\n" +
				"\t\t\t<input id=\"quote-email\" type=\"text\" name=\"email\" />\n" +
				"\t\t</div>\n" +
				"\t</div>\n" +
				"\t<div class=\"group cfx\">\n" +
				"\t\t<div class=\"el\">\n" +
				"\t\t\t<label for=\"quote-phone\">Phone <span class=\"reqd\">(required)</span></label>\n" +
				"\t\t\t<input id=\"quote-phone-areacode\" type=\"text\" name=\"phone[areacode]\" />\n" +
				"\t\t\t<input id=\"quote-phone\" type=\"text\" name=\"phone[number]\" />\n" +
				"\t\t</div>\n" +
				"\t\t<div class=\"el\">\n" +
				"\t\t\t<label for=\"quote-company\">Company</label>\n" +
				"\t\t\t<input id=\"quote-company\" type=\"text\" name=\"company\" />\n" +
				"\t\t</div>\n" +
				"\t</div>\n" +
				"\t<div class=\"el\">\n" +
				"\t\t<label for=\"quote-message\">Description of your website needs <span class=\"reqd\">(required)</span></label>\n" +
				"\t\t<textarea id=\"quote-message\" name=\"message\"></textarea>\n" +
				"\t</div>\n" +
				"\t<div class=\"el\">\n" +
				"\t\t<input class=\"btn\" type=\"submit\" name=\"submit\" value=\"Submit Form\" />\n" +
				"\t</div>\n" +
				"</form>\n"
			);

			this.bubbleBox.setContent(html);
			this.bubbleBox.open();
		},
		validate : function () {
			var form = $("#request-quote-form");
			$.get("/wp-content/themes/carbonated/_includes/ajax/validate-request-proposal.xml.php", {
				name : form.find("[name=\"name\"]").val(),
				email : form.find("[name=\"email\"]").val(),
				"phone-areacode" : form.find("[name=\"phone[areacode]\"]").val(),
				"phone-number" : form.find("[name=\"phone[number]\"]").val(),
				company : form.find("[name=\"company\"]").val(),
				message : form.find("[name=\"message\"]").val()
			}, function (xml) {
				// remove any old error messages
				$("#request-quote-form .error").remove();

				var errors = false;
				var elements = [];
				elements["name"] = "#request-quote-form [name=\"name\"]";
				elements["email"] = "#request-quote-form [name=\"email\"]";
				elements["phone"] = "#request-quote-form [name=\"phone[number]\"]";
				elements["message"] = "#request-quote-form [name=\"message\"]";

				$(xml).find("result").each(function () {
					if ($(this).attr("type") == "error") {
						// add the error message to the element
						var el = $(elements[$(this).attr("el")]);
						var message = "<span class=\"error\">" + $(this).text() + "</span>";

						errors = true;

						el.parents(".el").append(message);
					}
				});

				if (!errors) {
					form.hide();
					var html = (
						"<h1>Thank You!</h1>" +
						"<p>Thank you for contacting Carbonated with a proposal request.</p>"
					);
					form.after(html);
				}

			});
		}
	};
	requestProposal.init();

	var teamBios = {
		init : function () {
			if (!$("#team-overview").length) {
				return false;
			}

			this.bubbleBox = new CRB_BubbleBox({
				close : this.unload
			});
			this.bubbleBox.init();

			this.loading = new Image();
			this.bioOpened = false;
			this.team = [];

			// start loading the loading graphic
			this.loading.src = "/wp-content/themes/carbonated/_common/images/loading.gif";

/*
			// get XML data and parse into Javascript objects
			var self = this;
			$.get("/wp-content/themes/carbonated/_includes/data/carbonated-team.xml",function(xml) {
				// parse team data
				$(xml).find("member").each(function() {
	
					var id = $(this).attr("id");
	
					var member = {};
					member.name = $(this).find("name").text();
					member.title = $(this).find("title").text();
					member.description = $(this).find("description").text();
					member.facts = $(this).find("facts").text();
					member.likes = [];
					$(this).find("likes").find("like").each(function() {
						member.likes.push($(this).text());
					});
					member.dislikes = [];
					$(this).find("dislikes").find("dislike").each(function() {
						member.dislikes.push($(this).text());
					});
					member.photo = $(this).find("photo").text();
	
					self.team[id] = member;
				});
			});
*/

			// Extract team data from hidden HTML
			var self = this;
			$("#team-bio-data > li").each(function () {
				var id = $(this).find(".id").html();

				var member = {};
				member.name = $(this).find(".name").html().trim();
				member.title = $(this).find(".title").html().trim();
				member.description = $(this).find(".description").html().trim();
				member.facts = $(this).find(".facts").html().trim();
				member.likes = [];
				$(this).find(".likes li").each(function () {
					member.likes.push($(this).html().trim());
				});
				member.dislikes = [];
				$(this).find(".dislikes li").each(function () {
					member.dislikes.push($(this).html().trim());
				});
				member.photo = $(this).find(".photo").html().trim();
	
				self.team[id] = member;
			});

			// bind open events, now that we have data to show
			$("#team-overview .thb").click(function () {
				self.load($(this).find("[name=\"id\"]").val());
				return false;
			});
		},
		getBioText : function (member) {
			var likes = "";
			if (member.likes.length) {
				likes = "<p>" + member.likes.join(", ").ucFirst() + "</p>";
			}
			var dislikes = "";
			if (member.dislikes.length) {
				dislikes = "<p>" + member.dislikes.join(", ").ucFirst() + "</p>";
			}

			var html = (
				"<h1 class=\"grunge-font\">" + member.name + "</h1>" +
				"<h2>" + member.title + "</h2>" +
				member.description
			);
			if (member.facts) {
				html += (
					"<h2>Useless Facts</h2>" +
					member.facts
				);
			}
			if (likes) {
				html += (
					"<div class=\"likes\">" +
					"<h2>Likes</h2>" +
					likes +
					"</div>"
				);
			}
			if (dislikes) {
				html += (
					"<div class=\"dislikes\">" +
					"<h2>Dislikes</h2>" +
					dislikes +
					"</div>"
				);
			}

			return html;
		},
		load : function (id) {
			this.bioOpened = id;

			var member = this.team[id];

			// create necessary HTML elements
			this.bubbleBox.setContent(
				"\t\t\t<div class=\"avatar\">\n" +
				"\t\t\t\t<img class=\"loading\" src=\"" + this.loading.src + "\" alt=\"Loading...\" width=\"" + this.loading.width + "\" height=\"" + this.loading.height + "\"/>\n" +
				"\t\t\t</div>\n" +
				"\t\t\t<div class=\"bio\">\n" +
				this.getBioText(member) +
				"\t\t\t</div>\n"
			);

			// start loading bio picture
			var bio = new Image();
			bio.id = id;
			var self = this;
			bio.onload = function () {
				// if bio being viewed/last viewed contains this image, replace the loading graphic
				if (self.bioOpened == this.id) {
					$("#bubble-box .avatar").html("<img src=\"" + bio.src + "\" alt=\"" + member.name + "\" width=\"" + bio.width + "\" height=\"" + bio.height + "\"/>");
				}
			};
			bio.src = "/wp-content/themes/carbonated/_common/images/avatars/lrg-" + member.photo;

			this.bubbleBox.open();
		},
		unload : function () {
			teamBios.bioOpened = false;
		}
	};
	teamBios.init();

	// --------------------------------------------------------------------------------

	function CRB_inputValueAsLabel(el) {
		var text = $(el).val();
		$(el).focus(function () {
			$(this).addClass("active");
			if (!this.changed) {
				$(this).val("");
			}

			return;
		}).blur(function () {
			$(this).removeClass("active");
			if ((this.changed && !$.trim($(this).val())) || !this.changed) {
				this.changed = false;
				$(this).val(text);
			}

			return;
		}).keypress(function () {
			this.changed = true;
	
			return;
		});

		return;
	}

	// --------------------------------------------------------------------------------

	var contactForm = {
		oldLength:0,
		init:function () {
			// bind events
			var el = $("input[name=\"phone[areacode]\"]");
			if (!el.length) {
				return false;
			}

			var self = this;
			el.keyup(function () {
				/*
					if this is the length of the string is 3 characters, and the previous length
					before pressing a key was less than 3 characters, (Don't move if not adjusting value)
					move to the next field. If you paste in three numbers, this won't work, as the length
					won't have changed.
				*/
				if ($(this).val().length == 3 && self.oldLength < 3) {
					$("input[name=\"phone[phonenumber]\"]").focus().select();
				}
				self.oldLength = $(this).val().length;
			});
		}
	};
	contactForm.init();

	// --------------------------------------------------------------------------------

	var newsletterSubscribeForm = {
		init:function () {
			var el = $("#newsletter-subscribe");
			if (!el.length) {
				return false;
			}

			new CRB_inputValueAsLabel(el.find("[name=\"fname\"]"));
			new CRB_inputValueAsLabel(el.find("[name=\"lname\"]"));
			new CRB_inputValueAsLabel(el.find("[name=\"email\"]"));
		}
	};
	newsletterSubscribeForm.init();

	// --------------------------------------------------------------------------------

	var searchForm = {
		init:function () {
			var el = $("#sidebar-search");
			if (!el.length) {
				return false;
			}

			new CRB_inputValueAsLabel(el.find("[name=\"s\"]"));
		}
	};
	searchForm.init();

	// --------------------------------------------------------------------------------

	var searchForm404 = {
		init:function () {
			var el = $("#search-404");
			if (!el.length) {
				return false;
			}

			new CRB_inputValueAsLabel(el.find("[name=\"s\"]"));
		}
	};
	searchForm404.init();

	// --------------------------------------------------------------------------------

	var searchFailForm = {
		init:function () {
			var el = $("#search-fail");
			if (!el.length) {
				return false;
			}

			new CRB_inputValueAsLabel(el.find("[name=\"s\"]"));
		}
	};
	searchFailForm.init();

	// --------------------------------------------------------------------------------

	var salespageForm = {
		init:function () {
			var el = $("#fixbox_subscribe");
			if (!el.length) {
				return false;
			}

			new CRB_inputValueAsLabel(el.find("[name=\"email\"]"));
		}
	};
	salespageForm.init();

	// --------------------------------------------------------------------------------

	function CRB_ThreePaneViewer() {
		this.els = {};
		this.els.slidesContainer = "#promo-wordpress .slides";
		this.els.slides = "#promo-wordpress .slides img";
		this.els.controls = "#promo-wordpress .controls";

		this.pos = {};
		this.pos.stageLeft = {};
		this.pos.stageLeft.x = -394;
		this.pos.stageLeft.y = 30;
		this.pos.stageRight = {};
		this.pos.stageRight.x = 940;
		this.pos.stageRight.y = 30;
		this.pos.center = {}
		this.pos.center.x = 219;
		this.pos.center.y = 0;
		this.pos.left = {};
		this.pos.left.x = 80;
		this.pos.left.y = 30;
		this.pos.right = {};
		this.pos.right.x = 466;
		this.pos.right.y = 30;

		this.size = {};
		this.size.primary = {};
		this.size.primary.width = 502;
		this.size.primary.height = 297;
		this.size.normal = {};
		this.size.normal.width = 394;
		this.size.normal.height = 233;

		this.seq = {};
		this.seq.length = $(this.els.slides).length;	// The number of slides in the sequence
		this.seq.current = 0;							// The index of the 'primary' slide
		this.seq.next = 1;								// The index of the next slide in the sequence
		this.seq.prev = this.seq.length - 1;			// The index of the previous slide in the sequence

		this.init = function () {
			this.loadImages();
			this.bindControls();

			// show control buttons
			$(this.els.controls).show();
		};

		/*
		*	The images involved in this viewer are moderately large PNG files.
		*	The three images to be shown by default should be already loaded.
		*	Any additional images get loaded after by using the data-src attribute in the HTML:
		*	<img src="[path to image] ...               - default loaded image
		*	<img src="#" data-src="[path to image]" ... - post-loaded image
		*	N.B. since the default view is to display the first entry in the image sequence as the current/primary,
		*	the three images that should be loaded with the page are not the first three, but the first, second and last in the sequence.
		*/
		this.loadImages = function () {
			var self = this;

			$(this.els.slides).each(function(id) {
				var postLoadImage;
				if ($(this).attr("data-src")) {
					postLoadImage = new Image();
					postLoadImage.onload = function () {
						$(self.els.slides).eq(id).attr("src", this.src);
					};
					postLoadImage.src = $(this).attr("data-src");
				}
			});
		};

		this.bindControls = function () {
		};

		/*
		*	Animate an advance action - Shift the slides to highlight the next in the sequence
		*/
		this.advance = function () {
			var self = this;
			var prevSlide = $(this.els.slides).eq(this.seq.prev);
			var currentSlide = $(this.els.slides).eq(this.seq.current);
			var nextSlide = $(this.els.slides).eq(this.seq.next);
			var newSlide = this.seq.next + 1;

			// if animation in progress, return
			if (currentSlide.queue().length) {
				return;
			}

			// move and fade position 1 out of view to the left
			prevSlide.animate({
				left : this.pos.stageLeft.x,
				top : this.pos.stageLeft.y,
				opacity : 0
			}, 500);

			// move and shrink primary slide to position 1
			currentSlide.animate({
				left : this.pos.left.x,
				top : this.pos.left.y,
				width : this.size.normal.width,
				height : this.size.normal.height
			}, 100, function () {
				prevSlide.css({
					"z-index" : 200
				});
				$(this).css({
					"z-index" : 210
				});
			});

			// move and expand position 3 into position 2
			nextSlide.css({
				"z-index" : 220
			});
			nextSlide.animate({
				left : this.pos.center.x,
				top : this.pos.center.y,
				width : this.size.primary.width,
				height : this.size.primary.height
			}, 500, function () {
				$(this).css({
					"z-index" : 230
				});
			});

			// place next slide in sequence (primary + 2) on right side, just out of view, and fade in and move into position 3
			if (newSlide >= this.seq.length) {
				newSlide = 0;
			}
			newSlide = $(this.els.slides).eq(newSlide);
			newSlide.css({
				left : this.pos.stageRight.x,
				top : this.pos.stageRight.y,
				"z-index" : 200,
				opacity : 0
			});
			newSlide.animate({
				left : this.pos.right.x,
				top : this.pos.right.y,
				opacity : 1
			}, 500, function () {
				$(this).css({
					"z-index" : 210
				});
			});

			// update sequence
			var tempCurrent = this.seq.current;
			this.seq.current = this.seq.next;
			this.seq.prev = tempCurrent;
			this.seq.next += 1;
			if (this.seq.next >= this.seq.length) {
				this.seq.next = 0;
			}
		};

		/*
		*	Animate a retreat action - Shift the slides to highlight the previous in the sequence
		*/
		this.retreat = function () {
			var self = this;
			var nextSlide = $(this.els.slides).eq(this.seq.next);			
			var currentSlide = $(this.els.slides).eq(this.seq.current);
			var prevSlide = $(this.els.slides).eq(this.seq.prev);
			var newSlide = this.seq.prev - 1;

			// if animation in progress, return
			if (currentSlide.queue().length) {
				return;
			}

			// move and fade position 3 out of view to the right
			nextSlide.animate({
				left : this.pos.stageRight.x,
				top : this.pos.stageRight.y,
				opacity : 0
			}, 500);

			// move and shrink primary slide to position 3
			currentSlide.animate({
				left : this.pos.right.x,
				top : this.pos.right.y,
				width : this.size.normal.width,
				height : this.size.normal.height
			}, 100, function () {
				nextSlide.css({
					"z-index" : 200
				});
				$(this).css({
					"z-index" : 210
				});
			});

			// move and expand position 1 into position 2
			prevSlide.css({
				"z-index" : 220
			});
			prevSlide.animate({
				left : this.pos.center.x,
				top : this.pos.center.y,
				width : this.size.primary.width,
				height : this.size.primary.height
			}, 500, function () {
				$(this).css({
					"z-index" : 230
				});
			});

			// place previous slide in sequence (primary - 2) on the left side, just out of view, and fade in and move into position 1
			if (newSlide < 0) {
				newSlide = this.seq.length - 1;
			}
			newSlide = $(this.els.slides).eq(newSlide);
			newSlide.css({
				left : this.pos.stageLeft.x,
				top : this.pos.stageLeft.y,
				"z-index" : 200,
				opacity : 0
			});
			newSlide.animate({
				left : this.pos.left.x,
				top : this.pos.left.y,
				opacity : 1
			}, 500, function () {
				$(this).css({
					"z-index" : 210
				});
			});

			// update sequence
			var tempCurrent = this.seq.current;
			this.seq.current = this.seq.prev;
			this.seq.next = tempCurrent;
			this.seq.prev -= 1;
			if (this.seq.prev < 0) {
				this.seq.prev = this.seq.length - 1;
			}
		};
	}

	var promoWordpress = new CRB_ThreePaneViewer();
	promoWordpress.bindControls = function () {
		var self = this;
		$("#promo-wordpress .controls > li.next a").click(function () {
			self.advance();
			return false;
		});
		$("#promo-wordpress .controls > li.prev a").click(function () {
			self.retreat();
			return false;
		});
		
		$("#promo-wordpress .slides img").each(function(id) {
			$(this).click(function () {
				if (id == self.seq.next) {
					self.advance();
				} else if (id == self.seq.prev) {
					self.retreat();
				}
			});
		});
			
	};
	promoWordpress.init();

	// --------------------------------------------------------------------------------

	function CRB_TabbedDialog() {

		this.init = function () {
			var self = this;

			// hide all content areas but the first
			$(".tabbed-dialog > li:not(:first-child)").hide();
			// set the first tab as the active tab
			$(".tabbed-dialog > li:first-child .tab").addClass("active");

			// put the pointer/hand cursor on tabs
			$(".tabbed-dialog > li .tab").css({
				cursor : "pointer"
			});

			// bind events to tabs
			$(".tabbed-dialog > li .tab").each(function (id) {
				$(this).click(function () {
					self.goToTab(id);
				});
			});

			// move and aggregate tabs to a new location
			$(".tabbed-dialog").before(
				"<ul class=\"tabbed-dialog-tabs-list\">" +
				"</ul>"
			);
			$(".tabbed-dialog > li .tab").each(function () {
				$(this).appendTo(".tabbed-dialog-tabs-list").wrap("<li></li>");
			});
		};

		this.goToTab = function (id) {
			// hide content area of all tabs
			$(".tabbed-dialog > li").hide();
			// show content area for selected tab
			$(".tabbed-dialog > li").eq(id).show();
			// remove active class from all tabs
			$(".tabbed-dialog-tabs-list > li .tab").removeClass("active");
			// add active class to selected tab
			$(".tabbed-dialog-tabs-list > li .tab").eq(id).addClass("active");
		};
	}

	new CRB_TabbedDialog().init();

}());
