/**
 * jQuery YouTube Chromless Plugin v0.1
 * Copyright (c) 2009 Tom Rodenberg <tarodenberg gmail com>
 */
/**
 * Depenencies: jQuery 1.3.2, swfobject 2.1
 *
 * Custom Events:
 * 	Global:
 * 		-YouTubeReadyGlobal
 *		-YouTubeStateChangeGlobal,
 * 	Element Specific:
 * 		-YouTubeReady
 *		-YouTubeStateChange
 */
(function($) {
/**
 * Private variables
 */
var dataId = 'youtube', 
	nullFn = function() {},
	defaultControlPrefix = "youtubeplayer_",
	chromelessUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1',
	standardPlayerUrl = 'http://www.youtube.com/',
	onReadyOld,
	stateChangeListener,
	stateChangeListenerFn = 'youTubeStateChangeListener',
	states = {
		"-1": "unstarted",
		0: "ended",
		1: "playing",
		2: "paused",
		3: "buffering",
		5: "cued"
	},
	/** 
	 * An associative array containing all jquery youtube players
	 */
	players = {};

/**
 * A list of default options
 */
var defaultOptions = {
	/**
	 * You tube player we want to use
	 */
	playerUrl: chromelessUrl,
	
	/**
	 * ID for the flash player. [optional]
	 */
	playerId: null,
	
	/**
	 * Automatically start playing the first video in the playlist when the player is laoded
	 */
	autoplay: false,
	
	/**
	 * Width in pixels
	 */
	width: 320,
	
	/**
	 * Height in pixels
	 */ 
	height: 240,
	
	/**
	 * Background color for video and controls
	 */
	backgroundColor: '#CCCCCC',
	
	/**
	 * function to execute when the player is ready
	 * This might currently only fire when cueing a video
	 * change to onCue?
	 */
	onReady: nullFn,
	
	/** 
	* function to execute when the player begins playback
	*/
	onPlay: nullFn,
	
	/**
	 * function to execute when the player is paused
	 */
	onPause: nullFn,
	
	/**
	 * function to execute when the player is stopped
	 */
	onStop: nullFn,
	
	/**
	 * function to execute when the player state changes
	 * The function to be implemented will be called as follows:
	 *	function(player, playerId, state)
	 *		player: Player JS Object
	 *		playerId: Player String ID
	 *		state: number / Possible values of state are unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5). 
	 *		stateText: string / Possible values of stateText are 'unstarted', 'ended', 'playing', 'paused', 'buffering', 'cued'. 
	 */
	onStateChange: nullFn,
	
	/**
	 * List of videos we want to play.  string or string[]
	 */
	playlist: [],
	
	/**
	 * Enables or disables javascript control creation
	 */
	createControls: false,
	
	/**
	 * Enables high quality video feed option.  May not work for all videos.
	 * Since the method used to access the high quality feed is undocumented, this feature may break in the future.
	 * TODO: make detectable?
	 */
	highQuality: false,
	
	/**
	 * URL path to Express Flash installer for Internet Explorer.
	 * For use with SWFObject plugin.
	 */
	expressUrl: null
}

/**
  * Plugin command interpreter
  * Returns the jQuery selector when initializing
  * Returns an object if passing an option.  The object is a value for the first item in the selector.
  */
$.fn.youtube = function(options) {
	var returnVal, 
		args = Array.prototype.slice.call(arguments, 1),
		stringArg = typeof options == "string";
	
	this.each(function() {
		if (stringArg) {
			var fn = $.data(this, dataId);
			var value = fn ? fn[options].apply(fn, args) : null;
			if(!returnVal) {
				returnVal = value;
			}
		} 
		
		// initialize the player with options
		else if (!$(this).data(dataId)) {
			return $.data(this, dataId, new youtube(this, options));
		}
	});
	
	return stringArg ? returnVal : this;
}

/**
 * Embeds a YouTube player into an HTML object.
 *
 * buildId: string ID for the embed object that will be created -- this is the ID through which
 *			the YouTube API will be accessed.
 * insertId: string ID for the already existant HTML object where the video should appear
 * swf: remote Flash SWF link for the YouTube API of choice
 * width: width of the embed object to be built
 * height: height of the embed object to be built
 */
var buildYouTubePlayer = function(buildId, insertId, swf, width, height, bgcolor, highQuality, expressUrl)
{
	if(window.swfobject) {
		// Load YouTube player
		var params = { 
			allowScriptAccess: "always",
			bgcolor: bgcolor, 
			wmode: "opaque" 
		}
		
		var atts = { 
			id: buildId 
		}
		
		var flashvars = {
			enablejsapi: 1,
			playerapiid: insertId
		}
		
		// This is undocumented and may break in the future
		if(highQuality) {
			//fmt=18
			flashvars.ap = '%2526fmt%3D18';
		}
		
		//swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes)
		swfobject.embedSWF(swf, insertId, width, height, "8", expressUrl, flashvars, params, atts);
	}
	else {
		$('#' + insertId).html('Unable to locate swfobject flash loader');
	}
};

/**
 * Defines a global collection that will contain event listener functions.
 * A global var is required to support the Flash External Interface
 */
stateChangeListener = window[stateChangeListenerFn] = {};

// If the You Tube On Ready is expected by someone else, we will call it after	 
if(window.onYouTubePlayerReady) {
	onReadyOld = window.onYouTubePlayerReady;
}

/**
 * Default onready function as specified in the youtube javascript api
 */
window.onYouTubePlayerReady = function(playerId) {
	// Get the function associated with this player
	var player = players[playerId]		
	if(player) {
		var options = player.options;
		
		// create reference to the flash player
		var flashObject = $('#' + playerId);
		
		if(flashObject.length > 0) {
			player.flashPlayer = flashObject[0];
			
			//  create listener function for state change event handling
			player.flashPlayer.addEventListener("onStateChange", 
				stateChangeListenerFn + '.' + playerId);
			
			// Check if any items were added to the playlist
			if(options.playlist && options.playlist.length > 0) {
				var videoId = options.playlist[0];
				
				// Check if autoplay was set. If so, start playback immediately
				if(options.autoplay) {
					player.load(videoId);
				}
				
				// Otherwise, cue the video to display preview to user
				else {
					player.cue(videoId);
				}
			}
		}
		
		var eventData = [player, playerId];
		
		// Call the onready function if it was defined
		if(options.onReady) {
			options.onReady.apply(this, eventData);
		}
		
		// Trigger custom jquery YouTubeReady events
		$(player.element).trigger('YouTubeReady', eventData);
		$.event.trigger('YouTubeReadyGlobal', eventData);
	}

	// Call any previously defined onReady functions
	if(onReadyOld) {
		onReadyOld.apply(this, arguments);
	}
}

/**
 * Loads the flash player.
 * If a video id or playlist is specified, the first video will be loaded/cued.
 * @param container {DOM Object} 
 * @param options {Object} An associative array that contains option settings for this specific YouTube plugin object
 */
var youtube = function(container, options) {
	// Create reference to the jQuery object
	this.element = container;
	
	// Variable to keep track of the currently loaded Video ID
	this.currentVideoId = null;
	
	// Attempt to keep track of the current state
	this.currentState = -1;
	
	// Create options object using default options as a base
	this.options = options = $.extend({}, defaultOptions, options);
	
	// Keeps track of any existing onYouTubePlayerReady and onStateChange event handlers
	var onReadyOld,
		playerId = options.playerId, 
	// Reference to this function for anonymous functions declared within
		player = this;

	// If playlist is a string, convert to array
	if(typeof options.playlist == "string") {
		options.playlist = [options.playlist];
	}
	
	// If playerId is null, find an unused id
	for(var i = 0; playerId == null || $('#' + playerId).length > 0; i++) {
		playerId = defaultControlPrefix + i;
	}
	options.playerId = playerId;
	players[playerId] = this;
	
	// TODO: Create javascript controls for this player
	
	$(container).html('<div id="' + playerId + '"></div>');
	
	// Create the on state change event listener
	stateChangeListener[playerId] = function(state) {
		this.currentState = state;
		
		var eventData = [player, playerId, state, states[state]];
		
		// Call the onstatechange function if it was defined
		if(options.onStateChange) {
			options.onStateChange.apply(this, eventData);
		}
		
		// Call the onPlay function if it was defined
		if(state == 1 && options.onPlay) {
			options.onPlay.apply(this, eventData);
		}
		
		// Call the onPause function if it was defined
		if(state == 2 && options.onPause) {
			options.onPause.apply(this, eventData);
		}
		
		// Call the onStop function if it was defined
		// Is this correct? (state 0 is ended)
		if(state == 0 && options.onStop) {
			options.onStop.apply(this, eventData);
		}
		
		if(state == 5 && options.onReady) {
			options.onReady.apply(this, eventData);
		}
		
		// Trigger custom jquery YouTubeStateChange event
		$(container).trigger('YouTubeStateChange', eventData);
		$.event.trigger('YouTubeStateChangeGlobal', eventData);
	}
	
	// Create the flash player using SWFObject
	buildYouTubePlayer(playerId, playerId, options.playerUrl, 
		options.width, options.height, options.backgroundColor, options.highQuality, options.expressUrl);
}

/** 
 * Public functions
 */
youtube.prototype = {
	/**
	 * Loads a  video and starts playing
	 * @param videoId {string} video ID to load
	 * @param startSeconds {string/int} default starting time
	 */
	load: function(videoId, startSeconds) {
		if (this.flashPlayer && this.flashPlayer.loadVideoById) {
			this.currentVideoId = videoId;
			try { this.flashPlayer.loadVideoById(videoId, parseInt(startSeconds)); } catch(e) {}
		}
	},
	
	/**
	 * Cues a video for playback
	 * @param videoId {string} video ID to cue
	 */
	cue: function(videoId, startSeconds) {
		if (this.flashPlayer && this.flashPlayer.cueVideoById) {
			this.currentVideoId = videoId;
			try { this.flashPlayer.cueVideoById(videoId, parseInt(startSeconds || 0)); } catch(e) {}
		}
	},
	
	/**
	 * Start/Resume playback
	 * If a videoId is passed and it is different than the current video being played, then start new video playback.
	 * If videoId exists in the playlist, the playlist position will be updated.
	 * If videoId doesn't exist in the playlist, it will be added to the end of the playlist
	 */
	play: function(videoId) {
		if (this.flashPlayer && this.flashPlayer.playVideo) {
			try{ this.flashPlayer.playVideo(); } catch(e) {}
			if(this.options && this.options.onPlay) {
				this.options.onPlay();
			}
		}
	},
	
	/**
	 * Pause playback
	 */
	pause: function() {
		if (this.flashPlayer && this.flashPlayer.pauseVideo) {
			try{ this.flashPlayer.pauseVideo(); } catch(e){}
			if(this.options && this.options.onPause) {
				this.options.onPause();
			}
		}
	},
	
	/**
	 * Pause playback and reset the time to 0:00
	 */
	stop: function() {
		if (this.flashPlayer && this.flashPlayer.stopVideo) {
			try{ this.flashPlayer.stopVideo(); } catch(e){}
		}
	},
	
	/**
	 * Seeks to a specific time and starts playback
	 * @param seconds {number} Position in seconds from start
	 */
	seek: function(seconds) {
		if (this.flashPlayer && this.flashPlayer.seekTo) {
			try{ this.flashPlayer.seekTo(seconds, true); } catch(e) {}
		}
	},
	
	/**
	 * Seeks to a specific percent of total duration and starts playback
	 * @param seconds {number} Percent of total duration to start playback (1-100)
	 */
	seekPercent: function(percent) {
		if (this.flashPlayer && this.flashPlayer.seekTo) {
			try{ this.flashPlayer.seekTo((percent / 100) * this.getDuration(), true); } catch(e) {}
		}
	},
	
	/**
	* Plays the next video in the playlist if one exists
	* Returns the video ID of the new video, or null if no video exists
	*/
	next: function() {
		if (this.flashPlayer && this.options.playlist && this.options.playlist.length > 0) {
			var currentPos = $.inArray(this.options.playlist);
			var nextPos = currentPos + 1;
			if(nextPos < this.options.playlist.length) {
				var videoId = this.options.playlist[nextPos];
				this.load(videoId);
				return videoId;
			}
		}
	},
	
	/**
	 * Plays the previous video in the playlist if one exists
	 * Returns the video ID of the new video, or null if no video exists
	 */
	previous: function() {
		if (this.flashPlayer && this.options.playlist && this.options.playlist.length > 0) {
			var currentPos = $.inArray(this.options.playlist);
			if(currentPos > 0) {
				var videoId = this.options.playlist[currentPos - 1];
				this.load(videoId);
				return videoId;
			}
		}
	},
	
	/**
	 * Returns the state of the flash player
	 * @return {string} State Number
	 */
	getState: function() {
		if(this.flashPlayer && this.flashPlayer.getPlayerState) {
			try{ return this.flashPlayer.getPlayerState(); } catch(e) {}
		}
	},
	
	/**
	 * Resets the flash player to not have a video loaded.
	 */
	clearVideo: function() {
		if(this.flashPlayer && this.flashPlayer.clearVideo) {
			try{ return this.flashPlayer.clearVideo(); } catch(e) {}
		}
	},
	
	/**
	 * Returns the current volume level set on the flash player
	 */
	getVolume: function() {
		if(this.flashPlayer && this.flashPlayer.getVolume) {
			try{ return this.flashPlayer.getVolume(); } catch(e) {}
		}
	},
	
	/**
	 * Returns the length in seconds of the currently loaded video
	 */
	getDuration: function() {
		if(this.flashPlayer && this.flashPlayer.getDuration) {
			try{ return this.flashPlayer.getDuration(); } catch(e) {}
		}
		return -1;
	},
	
	/**
	 * Returns the current time play position
	 */
	getCurrentTime: function() {
		if(this.flashPlayer && this.flashPlayer.getCurrentTime) {
			try{ return this.flashPlayer.getCurrentTime(); } catch(e) {}
		}
		return -1;
	},
	
	/** 
	 * Returns the percent value (0-100) that represents the play position
	 */
	getPercentPlayed: function() {
		if(this.flashPlayer) {
			return parseFloat(this.getCurrentTime()) / parseFloat(this.getDuration()) * 100;
		}
		return 0;
	},
	
	/**
	 * Removes all traces of this plugin from the target control
	 */
	destroy: function() {
		if (this.flashPlayer) {
			try{ this.flashPlayer.stopVideo(); } catch(e) {}
			$(this.element).data(dataId, null).empty();
			this.flashPlayer = null;
		}
	}
}

/** 
 * Define 'static' methods
 */
$.youtube = $.extend( 
function(options) {
	var args = Array.prototype.slice.call(arguments, 1);
	if (typeof options == "string") {
		return $.youtube[options].apply(this, args);
	}
},
{
	/** 
	 * Stop all Youtube Players
	 */
	stop: function() {
		$.each(players, function() {
			this.stop();
		});
	},
	
	/** 
	 * Pause all Youtube Players
	 */
	pause: function() {
		$.each(players, function() {
			this.pause();
		});
	},

	/** 
	 * Start all Youtube Players
	 */
	play: function() {
		$.each(players, function() {
			this.play();
		});
	},
	
	/**
	 * Returns an associative array containing all youtube player objects keyed by player id.
	 */
	list: function() {
		return $.extend({}, players);
	},
	
	/** 
	 * Gets a player object by player ID
	 */
	getPlayer: function(playerId) {
		return players[playerId];
	},
	
	/** 
	* Returns the string value of a player state number
	*/
	getStateText: function(state) {
		return states[state];
	},
	
	/** 
	 * Formats a number to hh:mm:ss time string
	 */
	formatTime: function(s) {
		var time = parseInt(s);
		var timeString = '';
		var hasHours = false;
		if(time > 3600) {
			var hours = parseInt(time / 3600);
			time -= hours * 3600;
			hasHours = true;
			timeString += hours + ':';
		}
		var minutes = parseInt(time / 60);
		time -= minutes * 60;
		if(minutes < 10) {
			timeString += '0';
		}
		timeString +=  minutes + ':';
		if(time < 10) {
			timeString += '0';
		}
		timeString += time;
		return timeString;
	}
});

})(jQuery);

/*! reflection v1.6 for jquery
 * Contributors: Cow http://cow.neondragon.net
 *  Gfx http://www.jroller.com/page/gfx/
 *  Sitharus http://www.sitharus.com
 *  Andreas Linde http://www.andreaslinde.de
 *  Tralala, coder @ http://www.vbulletin.org
 *  Danny Ferguson, jquery plugin http://www.brendoman.com/dbc
 * Freely distributable under MIT-style license.
 */
(function(){
jQuery.fn.reflect = function(settings) {
	settings = jQuery.extend({
		height: 0.5,
		opacity: 0.5,
		inline: false
	}, settings);
	
	this.each( function() {
		var rheight = null;
		var ropacity = null;
		
		if (settings["inline"])
		{
			var classes = this.className.split(' ');
			for (j=0;j<classes.length;j++) {
				if (classes[j].indexOf("rheight") == 0) {
					settings["height"] = classes[j].substring(7)/100;
				} else if (classes[j].indexOf("ropacity") == 0) {
					settings["opacity"] = classes[j].substring(8)/100;
				}
			}
		}

		jQuery.Reflection.add(this, settings);
		
	})
	return this;
}

jQuery.Reflection = {
	
	add: function(image, options) {
		jQuery.Reflection.remove(image);
			
		try {
			var d = document.createElement('div');
			var p = image;
			
			var classes = p.className.split(' ');
			var newClasses = '';
			for (j=0;j<classes.length;j++) {
				if (classes[j] != "reflect") {
					if (newClasses) {
						newClasses += ' '
					}
					
					newClasses += classes[j];
				}
			}

			var reflectionHeight = Math.floor(p.height*options['height']);
			var divHeight = Math.floor(p.height*(1+options['height']));
			
			var reflectionWidth = p.width;
			
			if (document.all && !window.opera) {
				/* Copy original image's classes & styles to div */
				d.className = newClasses;
				p.className = 'reflected';
				
				d.style.cssText = p.style.cssText;
				p.style.cssText = 'vertical-align: bottom';
			
				var reflection = document.createElement('img');
				reflection.src = p.src;
				reflection.style.width = reflectionWidth+'px';
				
				reflection.style.marginBottom = "-"+(p.height-reflectionHeight)+'px';
				reflection.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(options['opacity']*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(options['height']*100)+')';
				
				d.style.width = reflectionWidth+'px';
				d.style.height = divHeight+'px';
				p.parentNode.replaceChild(d, p);
				
				d.appendChild(p);
				d.appendChild(reflection);
			} else {
				var canvas = document.createElement('canvas');
				if (canvas.getContext) {
					/* Copy original image's classes & styles to div */
					d.className = newClasses;
					p.className = 'reflected';
					
					d.style.cssText = p.style.cssText;
					p.style.cssText = 'vertical-align: bottom';
			
					var context = canvas.getContext("2d");
				
					canvas.style.height = reflectionHeight+'px';
					canvas.style.width = reflectionWidth+'px';
					canvas.height = reflectionHeight;
					canvas.width = reflectionWidth;
					
					d.style.width = reflectionWidth+'px';
					d.style.height = divHeight+'px';
					p.parentNode.replaceChild(d, p);
					
					d.appendChild(p);
					d.appendChild(canvas);
					
					context.save();
					
					context.translate(0,image.height-1);
					context.scale(1,-1);
					
					context.drawImage(image, 0, 0, reflectionWidth, image.height);
	
					context.restore();
					
					context.globalCompositeOperation = "destination-out";
					var gradient = context.createLinearGradient(0, 0, 0, reflectionHeight);
					
					gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
					gradient.addColorStop(0, "rgba(255, 255, 255, "+(1-options['opacity'])+")");
		
					context.fillStyle = gradient;
					if (navigator.appVersion.indexOf('WebKit') != -1) {
						context.fill();
					} else {
						context.fillRect(0, 0, reflectionWidth, reflectionHeight*2);
					}
				}
			}
		} catch (e) {
	    }
	},
	
	remove : function(image) {
		if (image.className == "reflected") {
			image.className = image.parentNode.className;
			image.parentNode.parentNode.replaceChild(image, image.parentNode);
		}
	}
}
})();

/*! Copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 */
(function($) {
	/**
	 * attaches a character counter to each textarea element in the jQuery object
	 * usage: $("#myTextArea").charCounter(max, settings);
	 */
	
	$.fn.charCounter = function (max, settings) {
		max = max || 100;
		settings = $.extend({
			container: "<span></span>",
			classname: "charcounter",
			format: "(%1 characters remaining)",
			pulse: true,
			delay: 0
		}, settings);
		var p, timeout;
		
		function count(el, container) {
			el = $(el);
			if (el.val().length > max) {
			    el.val(el.val().substring(0, max));
			    if (settings.pulse && !p) {
			    	pulse(container, true);
			    };
			};
			if (settings.delay > 0) {
				if (timeout) {
					window.clearTimeout(timeout);
				}
				timeout = window.setTimeout(function () {
					container.html(settings.format.replace(/%1/, (max - el.val().length)));
				}, settings.delay);
			} else {
				container.html(settings.format.replace(/%1/, (max - el.val().length)));
			}
		};
		
		function pulse(el, again) {
			if (p) {
				window.clearTimeout(p);
				p = null;
			};
			el.animate({ opacity: 0.1 }, 100, function () {
				$(this).animate({ opacity: 1.0 }, 100);
			});
			if (again) {
				p = window.setTimeout(function () { pulse(el) }, 200);
			};
		};
		
		return this.each(function () {
			var container = (!settings.container.match(/^<.+>$/)) 
				? $(settings.container) 
				: $(settings.container)
					.insertAfter(this)
					.addClass(settings.classname);
			$(this)
				.bind("keydown", function () { count(this, container); })
				.bind("keypress", function () { count(this, container); })
				.bind("keyup", function () { count(this, container); })
				.bind("focus", function () { count(this, container); })
				.bind("mouseover", function () { count(this, container); })
				.bind("mouseout", function () { count(this, container); })
				.bind("paste", function () { 
					var me = this;
					setTimeout(function () { count(me, container); }, 10);
				});
			if (this.addEventListener) {
				this.addEventListener('input', function () { count(this, container); }, false);
			};
			count(this, container);
		});
	};

})(jQuery);

/*!
 * jQuery Corners 0.3
 * Copyright (c) 2008 David Turnbull, Steven Wittens
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 */
(function() {
jQuery.fn.corners = function(options) {
  var doneClass = 'rounded_by_jQuery_corners'; /* To prevent double rounding */
  var settings = parseOptions(options);
  var webkitAvailable = false;
  try {
    webkitAvailable = (document.body.style.WebkitBorderRadius !== undefined);
    /* Google Chrome corners look awful */
    var versionIndex = navigator.userAgent.indexOf('Chrome');
    if (versionIndex >= 0) webkitAvailable = false;
  } catch(err) {}
  var mozillaAvailable = false;
  try {
    mozillaAvailable = (document.body.style.MozBorderRadius !== undefined);
    /* Firefox 2 corners look worse */
    var versionIndex = navigator.userAgent.indexOf('Firefox');
    if (versionIndex >= 0 && parseInt(navigator.userAgent.substring(versionIndex+8)) < 3) mozillaAvailable = false;
  } catch(err) {}
  return this.each(function(i,e){
    $e = jQuery(e);
    if ($e.hasClass(doneClass)) return;
    $e.addClass(doneClass);
    var classScan = /{(.*)}/.exec(e.className);
    var s = classScan ? parseOptions(classScan[1], settings) : settings;
    var nodeName = e.nodeName.toLowerCase();
    if (nodeName=='input') e = changeInput(e);
    if (webkitAvailable && s.webkit) roundWebkit(e, s);
    else if(mozillaAvailable && s.mozilla && (s.sizex == s.sizey)) roundMozilla(e, s);
    else {
      var bgColor = backgroundColor(e.parentNode);
      var fgColor = backgroundColor(e);
      switch (nodeName) {
        case 'a':
        case 'input':
          roundLink(e, s, bgColor, fgColor);
          break;
        default:
          roundDiv(e, s, bgColor, fgColor);
          break;
      }
    }
  });
  
  function roundWebkit(e, s) {
    var radius = '' + s.sizex + 'px ' + s.sizey + 'px';
    var $e = jQuery(e);
    if (s.tl) $e.css('WebkitBorderTopLeftRadius', radius);
    if (s.tr) $e.css('WebkitBorderTopRightRadius', radius);
    if (s.bl) $e.css('WebkitBorderBottomLeftRadius', radius);
    if (s.br) $e.css('WebkitBorderBottomRightRadius', radius);
  }
  
  function roundMozilla(e, s)
  {  
    var radius = '' + s.sizex + 'px';
    var $e = jQuery(e);
    if (s.tl) $e.css('-moz-border-radius-topleft', radius);
    if (s.tr) $e.css('-moz-border-radius-topright', radius);
    if (s.bl) $e.css('-moz-border-radius-bottomleft', radius);
    if (s.br) $e.css('-moz-border-radius-bottomright', radius);  
  }
  
  function roundLink(e, s, bgColor, fgColor) {
    var table = tableElement("table");
    var tbody = tableElement("tbody");
    table.appendChild(tbody);
    var tr1 = tableElement("tr");
    var td1 = tableElement("td", "top");
    tr1.appendChild(td1);
    var tr2 = tableElement("tr");
    var td2 = relocateContent(e, s, tableElement("td"));
    tr2.appendChild(td2);
    var tr3 = tableElement("tr");
    var td3 = tableElement("td", "bottom");
    tr3.appendChild(td3);
    if (s.tl||s.tr) {
      tbody.appendChild(tr1);
      addCorners(td1, s, bgColor, fgColor, true);
    }
    tbody.appendChild(tr2);
    if (s.bl||s.br) {
      tbody.appendChild(tr3);
      addCorners(td3, s, bgColor, fgColor, false);
    }
    e.appendChild(table);
    /* Clicking on $('a>table') in IE will trigger onclick but not the href  */
    if (jQuery.browser.msie) table.onclick = ieLinkBypass;
    /* Firefox 2 will render garbage unless we hide the overflow here */
    e.style.overflow = 'hidden';
  }
  
  function ieLinkBypass() {
    if (!this.parentNode.onclick) this.parentNode.click();
  }
  
  function changeInput(e) {
    var a1 = document.createElement("a");
    a1.id = e.id;
    a1.className = e.className;
    if (e.onclick) {
      a1.href = 'javascript:'
      a1.onclick = e.onclick;
    } else {
      jQuery(e).parent('form').each(function() {a1.href = this.action;});
      a1.onclick = submitForm;
    }
    var a2 = document.createTextNode(e.value);
    a1.appendChild(a2);
    e.parentNode.replaceChild(a1, e);
    return a1;
  }

  function submitForm() {
    jQuery(this).parent('form').each(function() {this.submit()});
    return false;
  }

  function roundDiv(e, s, bgColor, fgColor) {
    var div = relocateContent(e, s, document.createElement('div'));
    e.appendChild(div);
    if (s.tl||s.tr) addCorners(e, s, bgColor, fgColor, true);
    if (s.bl||s.br) addCorners(e, s, bgColor, fgColor, false);
  }
  
  function relocateContent(e, s, d) {
    var $e = jQuery(e);
    var c;
    while(c=e.firstChild) d.appendChild(c);
    if (e.style.height) {
      var h = parseInt($e.css('height'));
      d.style.height = h + 'px';
      h += parseInt($e.css('padding-top')) + parseInt($e.css('padding-bottom'));
      e.style.height = h + 'px';
    }
    if (e.style.width) {
      var w = parseInt($e.css('width'));
      d.style.width = w + 'px';
      w += parseInt($e.css('padding-left')) + parseInt($e.css('padding-right'));
      e.style.width = w + 'px';
    }
    d.style.paddingLeft = $e.css('padding-left');
    d.style.paddingRight = $e.css('padding-right');
    if (s.tl||s.tr) {
      d.style.paddingTop = adjustedPadding(e, s, $e.css('padding-top'), true);
    } else {
      d.style.paddingTop = $e.css('padding-top');
    }
    if (s.bl||s.br) {
      d.style.paddingBottom = adjustedPadding(e, s, $e.css('padding-bottom'), false);
    } else {
      d.style.paddingBottom = $e.css('padding-bottom');
    }
    e.style.padding = 0;
    return d;
  }
  
  function adjustedPadding(e, s, pad, top) {
    if (pad.indexOf("px") < 0) {
      try {
        //TODO Make this check work otherwise remove it
        console.error('%s padding not in pixels', (top ? 'top' : 'bottom'), e);
      }
      catch(err) {}
      pad = s.sizey + 'px';
    }
    pad = parseInt(pad);
    if (pad - s.sizey < 0) {
      try {
        console.error('%s padding is %ipx for %ipx corner:', (top ? 'top' : 'bottom'), pad, s.sizey, e);
      }
      catch(err) {}
      pad = s.sizey;
    }
    return pad - s.sizey + 'px';
  }

  function tableElement(kind, valign) {
    var e = document.createElement(kind)
    e.style.border = 'none';
    e.style.borderCollapse = 'collapse';
    e.style.borderSpacing = 0;
    e.style.padding = 0;
    e.style.margin = 0;
    if (valign) e.style.verticalAlign = valign;
    return e;
  }
  
  function backgroundColor(e) {
    try {
      var c = jQuery.css(e, "background-color");
      if ( c.match(/^(transparent|rgba\(0,\s*0,\s*0,\s*0\))$/i) && e.parentNode )
         return backgroundColor(e.parentNode);
      if (c==null)
        return "#ffffff";
      if (c.indexOf("rgb") > -1)
    	  c = rgb2hex(c);
      if (c.length == 4)
  	    c = hexShort2hex(c);
      return c;
    } catch(err) {
      return "#ffffff";
    }
  }
  
  function hexShort2hex(c) {
    return '#' +
    c.substring(1,2) +
    c.substring(1,2) +
    c.substring(2,3) +
    c.substring(2,3) +
    c.substring(3,4) +
    c.substring(3,4);
  }

  function rgb2hex(c) {
  	var x = 255;
  	var hex = '';
  	var i;
  	var regexp=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;
  	var array=regexp.exec(c);
  	for(i=1;i<4;i++) hex += ('0'+parseInt(array[i]).toString(16)).slice(-2);
  	return '#'+hex;
  }
  
  function parseOptions(options, settings) {
    var options = options || '';
    var s = {sizex:5, sizey:5, tl: false, tr: false, bl: false, br: false, webkit:true, mozilla: true, transparent:false};
    if (settings) {
      s.sizex = settings.sizex;
      s.sizey = settings.sizey;
      s.webkit = settings.webkit;
      s.transparent = settings.transparent;
      s.mozilla = settings.mozilla;
    }
    var sizex_set = false;
    var corner_set = false;
    jQuery.each(options.split(' '), function(idx, option) {
      option = option.toLowerCase();
      var i = parseInt(option);
      if (i > 0 && option == i + 'px') {
        s.sizey = i;
        if (!sizex_set) s.sizex = i;
        sizex_set = true;
      } else switch (option) {
        case 'no-native': s.webkit = s.mozilla = false; break;
        case 'webkit': s.webkit = true; break;
        case 'no-webkit': s.webkit = false; break;
        case 'mozilla': s.mozilla = true; break;
        case 'no-mozilla': s.mozilla = false; break;
        case 'anti-alias': s.transparent = false; break;
        case 'transparent': s.transparent = true; break;
        case 'top': corner_set = s.tl = s.tr = true; break;
        case 'right': corner_set = s.tr = s.br = true; break;
        case 'bottom': corner_set = s.bl = s.br = true; break;
        case 'left': corner_set = s.tl = s.bl = true; break;
        case 'top-left': corner_set = s.tl = true; break;
        case 'top-right': corner_set = s.tr = true; break;
        case 'bottom-left': corner_set = s.bl = true; break;
        case 'bottom-right': corner_set = s.br = true; break;
      }
    });
    if (!corner_set) {
      if (!settings) {
        s.tl = s.tr = s.bl = s.br = true;
      } else {
        s.tl = settings.tl;
        s.tr = settings.tr;
        s.bl = settings.bl;
        s.br = settings.br;
      }
    }
    return s;
  }
  
  function alphaBlend(a, b, alpha) {
    var ca = Array(
      parseInt('0x' + a.substring(1, 3)),
      parseInt('0x' + a.substring(3, 5)),
      parseInt('0x' + a.substring(5, 7))
    );
    var cb = Array(
      parseInt('0x' + b.substring(1, 3)),
      parseInt('0x' + b.substring(3, 5)),
      parseInt('0x' + b.substring(5, 7))
    );
    r = '0' + Math.round(ca[0] + (cb[0] - ca[0])*alpha).toString(16);
    g = '0' + Math.round(ca[1] + (cb[1] - ca[1])*alpha).toString(16);
    b = '0' + Math.round(ca[2] + (cb[2] - ca[2])*alpha).toString(16);
    return '#'
      + r.substring(r.length - 2)
      + g.substring(g.length - 2)
      + b.substring(b.length - 2);
  }

  function addCorners(e, s, bgColor, fgColor, top) {
    if (s.transparent) addTransparentCorners(e, s, bgColor, top);
    else addAntiAliasedCorners(e, s, bgColor, fgColor, top);
  }
  
  function addAntiAliasedCorners(e, s, bgColor, fgColor, top) {
    var i, j;
    var d = document.createElement("div");
    d.style.fontSize = '1px';
    d.style.backgroundColor = bgColor;
    var lastarc = 0;
    for (i = 1; i <= s.sizey; i++) {
      var coverage, arc2, arc3;
      // Find intersection of arc with bottom of pixel row
      arc = Math.sqrt(1.0 - Math.pow(1.0 - i / s.sizey, 2)) * s.sizex;
      // Calculate how many pixels are bg, fg and blended.
      var n_bg = s.sizex - Math.ceil(arc);
      var n_fg = Math.floor(lastarc);
      var n_aa = s.sizex - n_bg - n_fg;
      // Create pixel row wrapper
      var x = document.createElement("div");
      var y = d;
      x.style.margin = "0px " + n_bg + "px";
      x.style.height = '1px';
      x.style.overflow = 'hidden';
      // Create the pixel divs for a row (at least one)
      for (j = 1; j <= n_aa; j++) {
        // Calculate coverage per pixel (approximates arc within the pixel)
        if (j == 1) {
          if (j == n_aa) {
            // Single pixel
            coverage = ((arc + lastarc) * .5) - n_fg;
          }
          else {
            // First in a run
            arc2 = Math.sqrt(1.0 - Math.pow(1.0 - (n_bg + 1) / s.sizex, 2)) * s.sizey;
            coverage = (arc2 - (s.sizey - i)) * (arc - n_fg - n_aa + 1) * .5;
          }
        }
        else if (j == n_aa) {
          // Last in a run
          arc2 = Math.sqrt(1.0 - Math.pow((s.sizex - n_bg - j + 1) / s.sizex, 2)) * s.sizey;
          coverage = 1.0 - (1.0 - (arc2 - (s.sizey - i))) * (1.0 - (lastarc - n_fg)) * .5;
        }
        else {
          // Middle of a run
          arc3 = Math.sqrt(1.0 - Math.pow((s.sizex - n_bg - j) / s.sizex, 2)) * s.sizey;
          arc2 = Math.sqrt(1.0 - Math.pow((s.sizex - n_bg - j + 1) / s.sizex, 2)) * s.sizey;
          coverage = ((arc2 + arc3) * .5) - (s.sizey - i);
        }
        
        addCornerDiv(s, x, y, top, alphaBlend(bgColor, fgColor, coverage));
        y = x;
        var x = y.cloneNode(false);
        x.style.margin = "0px 1px";
      }
      addCornerDiv(s, x, y, top, fgColor);
      lastarc = arc;
    }
    if (top)
      e.insertBefore(d, e.firstChild);
    else
      e.appendChild(d);
  }
  
  function addCornerDiv(s, x, y, top, color) {
    if (top && !s.tl) x.style.marginLeft = 0;
    if (top && !s.tr) x.style.marginRight = 0;
    if (!top && !s.bl) x.style.marginLeft = 0;
    if (!top && !s.br) x.style.marginRight = 0;
    x.style.backgroundColor = color;
    if (top)
      y.appendChild(x);
    else
      y.insertBefore(x, y.firstChild);
  }

  function addTransparentCorners(e, s, bgColor, top) {
    var d = document.createElement("div");
    d.style.fontSize = '1px';
    var strip = document.createElement('div');
    strip.style.overflow = 'hidden';
    strip.style.height = '1px';
    strip.style.borderColor = bgColor;
    strip.style.borderStyle = 'none solid';
    var sizex = s.sizex-1;
    var sizey = s.sizey-1;
    if (!sizey) sizey = 1; /* hint for 1x1 */
    for (var i=0; i < s.sizey; i++) {
      var w = sizex - Math.floor(Math.sqrt(1.0 - Math.pow(1.0 - i / sizey, 2)) * sizex);
      if (i==2 && s.sizex==6 && s.sizey==6) w = 2; /* hint for 6x6 */
      var x = strip.cloneNode(false);
      x.style.borderWidth = '0 '+ w +'px';
      if (top) x.style.borderWidth = '0 '+(s.tr?w:0)+'px 0 '+(s.tl?w:0)+'px';
      else x.style.borderWidth = '0 '+(s.br?w:0)+'px 0 '+(s.bl?w:0)+'px';
      top ? d.appendChild(x) : d.insertBefore(x, d.firstChild);
    } 
    if (top)
      e.insertBefore(d, e.firstChild);
    else
      e.appendChild(d);
  }
}
})();

/*******************************************
 * page-reviews.js
 *******************************************
 * This script contains a class Reviews
 * for working with the reviews page.
 * 
 * It also maintains an initialization method
 * in the middle used for page creation.
 *
 * The end of this document holds some event
 * handlers for use with the YouTube JS API.
 * These handlers may change depending upon
 * the API in use for the page.
 *******************************************/

/** 
 * Simple plugin to make clearing form fields simple.
 * -- could stand to be externalized
 */
$.fn.clearForm = function() {
	return this.each(function() {
		var type = this.type, tag = this.tagName.toLowerCase();
		if (tag == 'form')
			return $(':input',this).clearForm();
		if (type == 'text' || type == 'password' || tag == 'textarea')
			this.value = '';
		else if (type == 'checkbox' || type == 'radio')
			this.checked = false;
	});
};

/**
 * Class Reviews contains a number of functions to manage the construction and actions that occur on
 * the reviews page.  The class is used in the JQuery init function at the bottom of this script.
 */
var Reviews = new function()
{	
	/**
	 * Creates the HTML necessary for a list of reviews to appear.  This function utilizes data in
	 * the "reviewData" object.
	 *
	 * reviewLength: character length at which review previews should be cut off
	 *
	 * Returns string of review HTML
	 */
	this.buildViewReviews = function(reviewLength)
	{
		var reviewsHtml = "";
		for( var review = 0; review < reviewData.length; review++ )
		{
			var body = reviewData[review].body.substr(0, reviewLength);
			body = body.
				replace(/(<p>|<div.*>)/gi,'').
				replace(/<\/p>|<\/div>|<br \/>/gi, '&nbsp;');
			
			// If the review contains more than 250 characters, then show the read more link;
			var showReadMoreLink = reviewData[review].body.length > reviewLength;
			
			
			reviewsHtml +=
				'<div class="review">' +
					'<h2>' + reviewData[review].title + '</h2>' +
					'<div class="body">' + body + 
					(showReadMoreLink ? '...&nbsp;<a rel="nofollow" href="javascript:Reviews.more(' + review + ');">read more</a>' : '') +
					'</div>' +
					'<div class="rating" style="width:' + reviewData[review].ratingwidth + '"></div>' +
					'<div class="signature">' + reviewData[review].signature + '</div>' +
					'<div style="clear:both;"></div>' +
				'</div>';
		}
		
		return reviewsHtml;
	};
	
	/**
	 * Performs the calculations and creates the HTML necessary for a pager object to appear
	 * below the reviews.  This can be finely tuned using the PHP variables in the page-reviews
	 * template.11:56 AM 12/16/2008
	 *
	 * reviewsHtml: HTML returned from the last step of construction for the reviews segment.
	 *				This function will simply add to the HTML as the final step.
	 *
     * currentPage: Number of the page we are currently on.
     * 
	 * Returns string of review HTML
	 */
	this.buildPager = function(reviewsHtml, currentPage)
	{
		if( maxPager >= 2 )
		{
            reviewsHtml += '<p class="review-pager" style="text-align:center;">';
        
            if(currentPage <= 1) {
                reviewsHtml += '&lt; ';
            }
            else {
                reviewsHtml += '<a rel="nofollow" href="javascript:void(0)" onclick="Reviews.pager(' + (currentPage - 1) + ');">&lt;</a> ';
            }
			
			for( var i = 1; i <= maxPager; i++ ) {
                
                if(i == currentPage) {
                    reviewsHtml += '<span class="current">' + i + '</span> ';
                }
                else {
                    reviewsHtml += '<a rel="nofollow" href="javascript:void(0)" onclick="Reviews.pager(' + i + ');">' + i + '</a> ';
                }
            }
            
            if(currentPage == maxPager) {
                reviewsHtml += '&gt;';
            }
            else {
                reviewsHtml += '<a rel="nofollow" href="javascript:void(0)" onclick="Reviews.pager(' + (currentPage + 1) + ');">&gt;</a>';
            }
            
			reviewsHtml += '</p>';
		}
		
		return reviewsHtml;
	};
	
	/**
	 * Builds review content for the specified pager page
	 *
	 * page: integer representing the page number to flip to
	 */
	this.pager = function(page)
	{
    
		$('#PaneReviews').html('<div class="loading">Loading customer reviews...</div>');
	
		// Set static height
        $('#PaneReviews').height($('#PaneReviews').height() + 10);
    
	 	// Ajax call for new review data
		$.getJSON("?pager=" + page, function(data)
		{
			reviewData = data;
			
			// Build HTML view of reviews
			var reviewsHtml = Reviews.buildViewReviews(250);
			
			// Add pager to list of reviews
			reviewsHtml = Reviews.buildPager(reviewsHtml, page);
			
			// Populate the reviews panel with content
			$('#PaneReviews').html(reviewsHtml);
			
			// round the corners
			$('#PaneReviews .review').corners('8px');
            
            // set dynamic height
            $('#PaneReviews').height('auto');
		});
	};
	
	/**
	 * Opens a dialog that displays the full review.  This function builds the full review on the fly.
	 *
	 * review: Each review has and ID number that can be used to call it in the mapped
	 *			array "reviewData".  This is that ID number to define which review should show in full.
	 *
	 * Todo: Build out a full review object in HTML and simply populate it from this function.  Don't
	 * 		re-build it every time.
	 */
	this.more = function(review)
	{
		$("#fullreviewcontents","#full-review-dialog").
		html(
			'<p>' +
				'<span class="text-bold">' + reviewData[review].title + '</span>' +
				'<br />' +
				'<span class="body text">' + reviewData[review].body + '</span>' +
			'</p>');
        GWR.Util.ShowModalDialog('#full-review-dialog', 550, 400);
	};
	
	/**
	 * Closes and clears the dialog with the full review showing.
	 */
	this.close = function()
	{
		$("#ReviewFull").hide().html('');
	};
	
	/**
	 * Submits a review and provides a simple confirmation to the user.
	 */
	this.submitReview = function()
	{
		//validate
		var errormsg = "";
		var title = $.trim ($('#title','#FormSubmitReview').val());
		var displayname = $.trim ($('#displayname','#FormSubmitReview').val());
		var lastname = $.trim ($('#lastname','#FormSubmitReview').val());
		var city = $.trim ($('#city','#FormSubmitReview').val());
		var state = $.trim ($('#state','#FormSubmitReview').val());
		var body = $.trim ($('#postBody','#FormSubmitReview').val());
		
		//default all the titles back to non-error style
		$(".label","#FormSubmitReview").removeClass("validation-error");
		
		if (title == "") {
			errormsg += "Review Title";
			$(".label[rel='title']","#FormSubmitReview").addClass("validation-error");
		}
		if (displayname == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "First Name";
			$(".label[rel='displayname']","#FormSubmitReview").addClass("validation-error");
		}
		if (lastname == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "Last Name";
			$(".label[rel='lastname']","#FormSubmitReview").addClass("validation-error");
		}		
		if (city == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "City";
			$(".label[rel='city']","#FormSubmitReview").addClass("validation-error");
		}	
		if (state == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "State";
			$(".label[rel='state']","#FormSubmitReview").addClass("validation-error");
		}	
		if (body == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "Review";
			$(".label[rel='body']","#FormSubmitReview").addClass("validation-error");
		}	
		if (errormsg != "") {
			$("#PaneSubmitReviewNotice").show().html(
				'Please enter the following fields before submitting:<br>' + errormsg
			 );
		}
		else {
			// passing the text value of the Property Visited option for the negative review email
			$('#emailpropertyname','#FormSubmitReview').val($('#propertyId option:selected').text());

			//$("#PaneSubmitReviewForm").hide();
			$("#PaneSubmitReviewNotice").show().html('Now submitting your review; please wait...');
			
			// Update submit button
			$('#butReviewSubmit').val("Submitting...");
			$('#butReviewSubmit').attr("disabled",true);
			
			var request = $("#FormSubmitReview").serialize();
			$.post("?post=true", request, function(data, status)
			{
				$("#PaneSubmitReviewNotice").html('Thank you, your submission has been successfully received.');
				$("#FormSubmitReview").clearForm();
				
				// Update submit button
				$('#butReviewSubmit').val("Submit Review");
				$('#butReviewSubmit').attr("disabled",false);
			}, "html");
		}
	};
	/**
	 * Allows user to enter an email for Greatwolf management to contact the person regarding a negative review.
	 * The email is processed and sent on submitReview();
	 */	
	this.getNegativeReviewEmail = function()
	{
		//validate
		var errormsg = "";
		var email = $.trim ($('#dialogemail').val());
	
		if (email == "") {
			errormsg = "Please provide your email address";
			$(".label[rel='email']").addClass("validation-error");
		}
		else {
			var validEmail = /^[\S]+[@][\S]+$/;
			var matchEmail = validEmail.exec(email);
			if (!matchEmail) {
				errormsg = "E-Mail Address is invalid (name@your-isp.com)";
			}		
		}
		if (errormsg != "") {
			$("#PaneSubmitNegativeReviewNotice").show().html(errormsg);
			$('#dialogemail').val('');
			$('#email').val('');
		}
		else {	
			var notice = 'Thank you, Great Wolf Management will be notified upon submission of this review.  We will contact you as soon as possible. ';
			$("#PaneSubmitNegativeReviewNotice").html(notice);
			$("#PaneSubmitNegativeReviewNotice").show();
			$("#review-notice-close").show();
			$('#email').val($('#dialogemail').val());
		}
	};
	
	/**
	 * Submits a youtube video and provides a simple confirmation to the user.
	 */
	this.submitVideo = function()
	{
		//validate
		var errormsg = "";
		var title = $.trim ($('#title','#FormSubmitVideo').val());
		var youtubeurl = $.trim ($('#youtubeurl','#FormSubmitVideo').val());
		var body = $.trim ($('#YoutubeDesc','#FormSubmitVideo').val());
		
		//default all the titles back to non-error style
		$(".label","#FormSubmitVideo").removeClass("validation-error");
		
		if (title == "") {
			errormsg += "Video Title";
			$(".label[rel='title']","#FormSubmitVideo").addClass("validation-error");
		}
		if (youtubeurl == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "Youtube URL";
			$(".label[rel='youtubeurl']","#FormSubmitVideo").addClass("validation-error");
		}
		if (body == ""){
			if (errormsg != ""){errormsg += ", "};
			errormsg += "Video Description";
			$(".label[rel='YoutubeDesc']","#FormSubmitVideo").addClass("validation-error");
		}	

		if (errormsg != "") {
			$("#PaneSubmitVideoNotice").show().html(
				'Please enter the following fields before submitting:<br>' + errormsg
			 );
		}
		else {
			$("#PaneSubmitVideoNotice").show().html('Now submitting your video; please wait...');
			
			// Update submit button
			$('#butVideoSubmit').val("Submitting...");
			$('#butVideoSubmit').attr("disabled",true);
			
			var request = $("#FormSubmitVideo").serialize();
			$.post("?post=true", request, function(data, status)
			{
				$("#PaneSubmitVideoNotice").html('Thank you, your submission has been successfully received.');
				$("#FormSubmitVideo").clearForm();
				
				// Update submit button
				$('#butVideoSubmit').val("Submit Video");
				$('#butVideoSubmit').attr("disabled",false);
			}, "html");
		}
	};
	
	/**
	 * Creates the HTML necessary for a line of thumbnail images.  This currently pulls from the
	 * "thumbnailData" mapped array.
	 *
	 * Returns string of thumbnail HTML
	 */
	this.buildViewThumbnails = function(startIndex)
	{
		if(!startIndex) {
			startIndex = 0;
		}
		var thumbnailHtml = '';
		for( var i = 0; startIndex + i < thumbnailData.length && i < 5; i++ ) {
			var thumbIndex = startIndex + i;
			thumbnailHtml += '<div rel="' + thumbIndex + '" class="thumbnail-border"><img alt="' + thumbnailData[thumbIndex].title + 
				'" src="' + thumbnailData[thumbIndex].image + '" /></div>';
		}	
		return thumbnailHtml;
	};
};

// Populate page with HTML structure
$(function()
{
	/*******************************************
	 * Character Counter for post review and post video
	 ********************************************/
	$("#postBody,#YoutubeDesc").charCounter(2000);

	/*******************************************
	 * UI Buildout
	 *******************************************/
	// Tab setup
	$("#Reviews").tabs();

	/*******************************************
	 * Reviews Segment
	 *******************************************/
	
	
	// Flip to the first page of reviews
	Reviews.pager(1);
    
	/**
	 * Negative Review dialog close button click event handler
	 */
	$('#negative-review-dialog .review-header .top-close').click(function() {
		GWR.Util.HideModalDialog();
	});    
	/**
	 * Full Review dialog close button click event handler
	 */
	$('#full-review-dialog .review-header .top-close').click(function() {
		GWR.Util.HideModalDialog();
	});      
	
	/*******************************************
	 * Video Segment
	 *******************************************/

	var renderThumbnails = function() {
		// Populate the thumbnail panel with content
		$('#Thumbnails').html(Reviews.buildViewThumbnails(thumbnailPage * 5));

		// Apply reflection visual effect
		$('#Thumbnails img').load(function() {
			$(this).reflect({
				height: 0.45,
				opacity: 0.3
			});
		});

		// Hide the next button if we are at the end of the list
		$('#thumbnail-next').toggle(thumbnailData.length / 5 > thumbnailPage + 1);

		// Hide the previous button if we are at the beginning
		$('#thumbnail-previous').toggle(thumbnailPage > 0);

		// Apply hover event to thumbnail images
		$('#Thumbnails .thumbnail-border').hover(function() {
			var thumbnailId = $(this).attr('rel');
			$('#video-title').html(thumbnailData[thumbnailId].title);
			$(this).addClass('hover');
		},
		function() {
			$('#video-title').html('');
			$(this).removeClass('hover');
		})

		// Apply click event to thumbnail images	
		.click(function() {
			// Add active class to the corresponding thumbnail border parent element
			$('#Thumbnails .thumbnail-border').removeClass('active');
			$(this).addClass('active');
		
			// Get the thumbnail index ID
			var thumbnailId = $(this).attr('rel');
			var videoId = thumbnailData[thumbnailId].id;
			$('#youtube-player-object').youtube('load', videoId);
		});
	}

	renderThumbnails();

	// Set first video in thumbnail list to active
	$('#Thumbnails .thumbnail-border:first').addClass('active');

	// Add click functionality if there are more than 5 data items
	if(thumbnailData.length > 5) {
		// Show the nav panel
		$('.thumbnail-nav').show();

		$('#thumbnail-next').click(function() {
			// Increment the global thumbnail page variable
			thumbnailPage++;
			$('#thumbnail-previous').show();
			renderThumbnails();
		});

		$('#thumbnail-previous').click(function() {
			// decrement the global thumbnail page variable
			thumbnailPage--;
			$('#thumbnail-next').show();
			renderThumbnails();
		});
	}
});

/*******************************************
 * trip advisor pager
 *******************************************/
function TripAdvisorPager(group) {
	$('.tripadvisor').hide();
	$(".tripadvisor[rel='" + group + "']","#PaneTripAdvisor").show();
	return false;
}

//{ YouTube Player Functions
/**
 * YouTube Player Functions
 */
 
/** 
 * Sets the time label on the player control panel given 2 numbers
 */
var setTimeLabel = function(current, total) {
	var currentTime = $.youtube.formatTime(current);
	var totalTime = $.youtube.formatTime(total);
	$('#slideshow-youtube .time').html(currentTime + ' / ' + totalTime);
}

/** 
 * Updates the player controls with the new play time
 */
var updateControls = function() {
	var yt = $('#youtube-player-object');
	if(yt.youtube('getState') == 1) {
		var time = yt.youtube('getCurrentTime');
		var totalTime = yt.youtube('getDuration');
	
		// Change percent on slider
		var percentLoaded = parseFloat(time) / parseFloat(totalTime) * 100;
		$('#slideshow-youtube .slider').slider('option', 'value', percentLoaded);
		
		// Set time
		setTimeLabel(time, totalTime);
	}
}

$(function() {
	var timer,
	// Starts the timer to update the time position
	// Also changes the play button into a pause button
	startTimer = function() {
		$('#slideshow-youtube .play').removeClass('play').addClass('pause');
		if(!timer) {
			timer = setInterval(updateControls, 250);
		}
	},
	
	// Stops the timer to update the time position
	// Also changes the pause button into a play button
	stopTimer = function() {
		$('#slideshow-youtube .pause').removeClass('pause').addClass('play');
		if(timer) {
			clearInterval(timer);
			timer = null;
		}
	};

	var firstVideo = thumbnailData[0];
	
	// Initialize the youtube player
	$('#youtube-player-object').youtube({
		playlist: firstVideo ? firstVideo['id'] : '',
		//autoplay: false,
		width:420,
		height:285,
		expressUrl: '/expressInstall.swf',
		onPlay: function() {
			startTimer();
		},
		onPause: function() {			
			stopTimer();
		},
		onStop: function() {
			stopTimer();
			$('#slideshow-youtube .slider').slider('option', 'value', 0);
		}
	});

	/**
	 * Initialize the slider jQuery UI widget
	 * The slider is used to display the video time position
	 */
	$('#slideshow-youtube .slider').slider({
		/**
		 * Stop updating the slider when user is clicking
		 */
		start: function() {
			stopTimer();
		},
		
		/**
		 * Retstart updating the slider when the user is done clicking
		 */
		stop: function() {
			startTimer();
		},
	
		/**
		 * Function that is called when the slider has slid to a new value but the final value of the slider is not determined.
		 */
		slide: function(e, ui) {
			var yt = $('#youtube-player-object');
			if(yt.youtube('getState') == 1) {
				var totalTime = yt.youtube('getDuration');
			
				// Get percent on slider
				var currentPercent = $(this).slider('option', 'value');
				
				var time = totalTime * (currentPercent / 100);
				
				// Set time
				setTimeLabel(time, totalTime);
			}
		},
		
		/**
		 * Function that is called when the value of slider has changed; mouse is released
		 */
		change: function(e, ui) {
			$('#youtube-player-object').youtube('seekPercent', ui.value);
		}
	});
	
	// Add onclick event to the youtube play button
	$('#slideshow-youtube .play').click(function() {
		if($(this).hasClass('play')) {
			$('#youtube-player-object').youtube('play');
		}
		else {
			$('#youtube-player-object').youtube('pause');
		}
	});
});
//}
