/**
 * @fileoverview	exploreli.com Homepage Feature Module Javascript
 * @author			Michael Bester <mbester@schematic.com>
 * @version			1.0
 * @dependencies	jquery.js (v.1.3.x)
 *					jquery.jcarousel.js
 *					global.js
 */

( XLI.FeatureModule = function() {

	/**
		A Flag to keep track of whether or not we've initialized this object.
	*/
	var initialized = false;

	/**
	 *	Set Some Constants
	 */
	var CONSTANTS = {

		// Featured Module ID
		MODULE_ID : "#feature",

		// The wrapper element for the whole carousel.
		CAROUSEL_VIEW_ID : "#featureCarousel",

		// Calendar Module ID
		CALENDAR_MODULE_ID : "featuredCalendar",

		// Carousel Selector
		CAROUSEL_SELECTOR : "ul.carousel",

		// Nav section class
		NAV_CLASS : "nav",

		// Carousel pager navigation class
		PAGER_CLASS : 'pager',

		// Wrapper class
		WRAPPER_CLASS : 'wrapper',

		// Quick Read ID / Class Name
		QUICK_READ_ID_CLASS : 'quickRead',

		// Scrim class name
		SCRIM_CLASS : 'scrim',

		// Quick read content class name
		CONTENT_CLASS : 'content',

		// "next" class name
		NEXT_CLASS : 'next',

		// "previous" class name
		PREV_CLASS : 'prev',

		// Class for button disabled state
		DISABLED_CLASS : 'disabled',

                // Class for navigational dot things
                DOTS_CLASS : 'dots',

		// Class to be applied to carousel slides only while animating. This is to work around a redraw bug on Firefox/PC
		ANIMATING_CLASS : 'animating',

		// overlay ajax target class
		CONTENT_TARGET_CLASS : 'contentTarget',

		// To indicate when a list nav item has a subnav.
		HAS_SUB_CLASS : 'hasSub',

		// Custom scrollbar container
		SCROLL_CONTAINER_CLASS : 'jScrollPaneContainer',

		// Section Reveal Scroll in/out Speed in milliseconds
		SCROLL_SPEED : 700,

		// animation speed of fading quickread in and out in milliseconds.
		QUICK_READ_SPEED : 200,

                // auto scroll delay in milliseconds
                AUTO_SCROLL_SPEED: null,

		// Text for quick read links
		QUICK_READ_TEXT : "Quick Read",

		// Quick read ad configuration
		QUICK_READ_AD_CONFIG : {
			width: 300,
			height: 250
		},

                // Feature carousel ad configuration
                FEATURE_AD_CONFIG : {
                       width: 300,
                       height: 250
                },

		// The number of slides at the end of the carousel which shouldn't be included in the total slide count
		SLIDE_OFFSET : 0


	};

	/**
	 *	Element References as returned by JQuery
	 *	references created as needed
	 */
	var $elements = {

		html : $('html'),

		// The Document
		document : $(document),

		// The featured module
		module : null,

		// Any scrollable panels in the module.
		scrollables : null,

		// The wrapper element for the whole carousel.
		carouselView : null,

		// Carousel List
		carousel : null,

		// Carousel Navigation
		pager : null,
                dots : null,

		// Nav section
		nav : null,

		// the actual nav list
		navList : null,

		// Quick Read
		quickRead : null,

		// Quick Read Nav
		quickReadNav : null,

		// Quick Read Nav
		quickReadNavNext : null,

		// Quick Read Nav
		quickReadNavPrev : null,

		// Quick Read Content section
		quickReadContent : null,

		// Quick Read Close Button
		quickReadClose : null,

		// scrim behind quick read
		scrim : null
	};

	/**
	 *	Shorthand references to the CONSTANTS and $elements.
	 */
	var C	= CONSTANTS;
	var $e	= $elements;

	/**
		a handle for the carousel
	*/
	var carousel = null;

	/**
		a handle for the carousel
	*/
	var quickReadIndex = 0;

	/**
		Intra-section animation flags
	*/
	var interstitialAnimation = false;
	var animateTransition = true;

	/**
	 * Sets up the homepage feature navigation, binding actions to each item.
	 * @private
	 * @returns nothing
	 */
	var initNav = function() {

		// Find some elements we'll need.
		$e.scrollables	= $e.module.find('.' + XLI.Global.C.SCROLLABLE_CLASS);
		$e.carouselView = $(C.CAROUSEL_VIEW_ID);
		$e.nav			= $e.module.find('.' + C.NAV_CLASS);
		$e.navList		= $e.nav.find('>ul');

		// set a reference to the default item;
		var $def;

		// Set up actions on the top level links
		$e.navList.find('>li').each(function(i){
			var rel,
				sn,
				$lis,
				$this = $(this),
				$that = $this;
			this.$siblings = $this.siblings();
			this.$link = $this.find('>a');
			this.$subnav = $this.find('ul.sub');
			rel = this.$link.attr('rel');

			// Set up the default item.
			if ($this.hasClass('default')) {
				$def = $this;
			}

			// Find the associated content overlay.
			if (rel) {
				rel = $(rel);
				if (rel.length) {
					this.$content = rel;
					// add a close button to each overlay
					$(XLI.Global.C.FLYOUT_CLOSE_HTML)
						.bind('click', function(e){
							e.preventDefault();

							// revert back to the first item
							activateSection($def);
						})
						.prependTo(this.$content);
				}
			}

			// And associate the carousel container to its nav element
			if (this.$link.attr('href') === C.CAROUSEL_VIEW_ID) {
				this.carousel = true;
			}

			// Subnav specific actions here.
			if (this.$subnav.length) {

				//$this.addClass(C.HAS_SUB_CLASS);

				sn = this.$subnav.get(0);

				// Get the height of the subnav
				sn.h = this.$subnav.height();

				// So we can do the subnav slide in and out,
				// let's set up a wrapper which we can use to hide it.
				this.$subnav.css('position','relative');
				this.$subnavWrapper = $('<div></div>')
								.css({
									'position' : 'relative',
									'overflow' : 'hidden',
									'z-index' : '10'
								})
								.insertBefore(this.$subnav)
								.append(this.$subnav)
								.hide();

				// get the subnav list elements
				$lis = this.$subnav.find('li');

				// Set up actions on any subnav links.
				this.$subnav.find('a[href!=#]').each(function(i){

					if (!rel) {
						return;
					}
					var $this = $(this),
						that = this;

					// get the subnav list elements
					this.$parentLis = $lis;

					// find where we'll be dropping new data
					this.$contentTarget = rel.find('.' + C.CONTENT_TARGET_CLASS);
					this.$scrollWrapper = rel.find('.' + XLI.Global.C.SCROLLABLE_CLASS);
					this.$contentTargetContainer = rel.find('.' + C.SCROLL_CONTAINER_CLASS);

					$this.bind('click', function(e){
						e.preventDefault();

						// deactivate any other active elements in this subnav
						that.$parentLis.removeClass(XLI.Global.C.ACTIVE_CLASS);
						// and add active to this one
						$this.parent().addClass(XLI.Global.C.ACTIVE_CLASS);

                                                // if the section is expanding, but we aren't the feed identified to be loaded by default, stop loading--just expand.
                                                var feedItemId = XLI.Global.State.getHashState("fF");

                                                if(feedItemId !== null) {
                                                       var id = $this.parent().attr("id");

                                                       if(id !== null && typeof id === 'string' && id.length > 0 && id !== feedItemId) {
                                                               return;
                                                       }
                                                }

						// Go and get new content
						try {
							var url = $this.attr('href');
                                                        var callback = "";

                                                        //if we're requesting from entriq, the function name cannot be dynamic--it's always "ws_results".
                                                        if(url.indexOf("entriq.net") >= 0) {
                                                                callback = "ws_results";
                                                        } else {
                                                                url = url + ((url.indexOf("?") >= 0) ? "&" : "?") + "callback=featuredModuleDataCallback";
                                                                callback = "featuredModuleDataCallback";
                                                        }

                                                        $.jsonp({
                                                                url: url,
                                                                callback: callback,
								cache: true,
								beforeSend : function() {
									that.$contentTarget.empty();
									that.$contentTargetContainer.addClass(XLI.Global.C.LOADING_CLASS);
									that.$scrollWrapper.jScrollPane();
								},
								success : function(data) {
									// that.$contentTarget.html(data);
									XLI.VideoJsonHandler.parse(data).appendTo(that.$contentTarget);
									that.$contentTargetContainer.removeClass(XLI.Global.C.LOADING_CLASS);

									// Fix for IE6 hover states
									XLI.Global.ie6Hover('li', that.$contentTarget);

									// delay this a bit because too many things are happening at once
									setTimeout(function() {
										that.$scrollWrapper.jScrollPane();
										$e.document.trigger("section:dataLoaded");
									}, 50);
								},
								error : function(xhr, message) {
									XLI.Debug.error("Error getting new content for feature module overlay: " + message);
									that.$contentTargetContainer.removeClass(XLI.Global.C.LOADING_CLASS);
								}
							});
						} catch(f) {
							XLI.Debug.error("Error getting new content for feature module overlay: " + f.message);
							that.$contentTargetContainer.removeClass(XLI.Global.C.LOADING_CLASS);
						}
					});

				});

				// Set up actions on any subnav items with sub items
				this.$subnav.children('li').children('a').bind('click',function(e){
					var $this = $(this);

					// side close any open subsubs
					$this.parent().siblings().find('.subsub').slideUp();
					// open current subsub
					$(this).siblings('.subsub').slideDown();
					e.preventDefault();
				});
			}

			this.$link.bind('click', function(e) {
				e.preventDefault();
				var $this = $(this);
				if (!$that.hasClass(XLI.Global.C.ACTIVE_CLASS)) {
					mediateSectionLoaded($this);
					activateSection($that, animateTransition);
				} else {
					mediateSectionLoaded($def);
					activateSection($def, animateTransition);
				}
			});
		});

		// override the default if need be - this is a dummy fallback
		if (!$def) {
			$def = $e.navList.find('>li:first');
		}

                var feedItemId = XLI.Global.State.getHashState("fF");

                if(feedItemId !== null) {
                        var $a = $("li#" + feedItemId + " a");

                        if($a.parent().parent().hasClass("subsub")) {
                                $a.parent().parent().show();
                        }

                        $a.click();
                }
	};

	/**
	 * Initializes any section-specific code once the subnav
	 * ajax call completes
	 * @private
	 * @params {jquery node} $contentTarget
	 * @returns nothing
	 */
 	var mediateSectionLoaded = function($link) {
		switch ($link.attr("rel")) {
			case "#featuredVideos" :
				XLI.LatestVideos.open();
			break;

			case "#featuredPhotos" :
				XLI.LatestVideos.cleanupPlayer();

				XLI.LatestPhotos.open();
			break;

			default:

			break;
		}
	};

	/**
	 * Sets up the feature carousel
	 * @private
	 * @returns nothing
	 */
	var initCarousel = function() {
		// Find some elements we'll need.
		$e.carousel		= $e.carouselView.find(C.CAROUSEL_SELECTOR);

		if (!$e.carousel.length || !$e.nav.length) {
			return;
		}

                // Fetch JSON feed and add slides to the carousel
                loadUnloadedContent();

                // make links set the state of the carousel via a hash tag when clicked
                $e.carousel.find("li a").live('click', function(e) {
                    var t = $(this);

                    if(t.hasClass("quickRead")) {
                        return;
                    }

                    e.preventDefault();

                    XLI.Global.State.resetHashState();
                    XLI.Global.State.setHashState("f", carousel.get(0).getFirstVisibleSlideIndex());
                    XLI.Global.State.syncHashState();

		    // drop cookie for Omniture to pick up when reporting
		    $.cookie("from", "feature");

                    window.location.href = $(this).attr("href");
                });

                // add JSON to elements for quick read functions
                $e.carousel.find("li").each(function(i) {
                       var $t = $(this);

                        if(! $t.hasClass("ad")) {
                               addQuickRead($t);
                        }
                });

                // initialize jcarousel
                var start = 0;

                try {
                       if(XLI.Global.State.getHashState("f") !== null) {
                               start = parseInt(XLI.Global.State.getHashState("f"),10);
                       } else {
                               start = 0;
                        }
                } catch(e) {
                       start = 0;
                }

               carousel = $e.carousel.parent().jCarouselLite({
                       btnNext: "#feature .nav .pager .next",
                       btnPrev: "#feature .nav .pager .prev",
                       scroll: 2,
                       visible: 2,
                       start: start,
                       auto: C.AUTO_SCROLL_SPEED,
                       speed: C.SCROLL_SPEED,
                       beforeStart: function(e) {
                                // hide ads in FF Windows because they mess up the navigation while moving
                                if(XLI.Global.win && XLI.Global.moz) {
                                        $e.carousel.find("li.ad iframe").css('visibility', 'hidden');
                                }
                       },
                       afterEnd: function(e) {
                               // reshow ads: (hide ads in FF Windows because they mess up the navigation while moving)
                               if(XLI.Global.win && XLI.Global.moz) {
                                       $e.carousel.find("li.ad iframe").css('visibility', 'visible');
                               }

                               renderAds(e);
                               updateDots();
                       }
               });

               // setup dot navigation UI
               $e.dots = $e.nav.find('.' + C.DOTS_CLASS);

               $e.dots.find("li").each(function(i) {
                       $n = $(this);

                       $n.attr("title", (i + 1));

                       $n.click(function(e) {
                               e.preventDefault();

                               var p = (($(this).attr("title") - 1) * 2);

                               carousel.get(0).go(p);
                       });
               });
        };


        var updateDots = function() {
                var p = carousel.get(0).getFirstVisibleSlideIndex();

                if(p !== null) {
                        $e.dots.find("li").removeClass("current");
                        $e.dots.find("li[title=" + (Math.floor(p / 2) + 1) + "]").addClass("current");
                }
        };

        var loadUnloadedContent = function() {
                if (!$.isArray(XLI.FeatureModule.unloadedSlideData)) {
                        return;
                }

                $.each(XLI.FeatureModule.unloadedSlideData, function() {
                        if (this.displayAd) {
                                var $adSlide = createAdSlideFromJSON(this);

                                $e.carousel.append($adSlide);
                        } else {
                                var $storySlide = createStorySlideFromJSON(this);

				if($storySlide) {
	                                // (save JSON for quickread builder)
        	                        $storySlide.data('slideData', this);

                	                $e.carousel.append($storySlide);
				}
                        }
                });

                XLI.FeatureModule.unloadedSlideData = null;
        };

        var renderAds = function($elements) {
                if (!XLI.AdManager.enabled) {
                        return;
                }

                $elements.filter("li.ad").each(function(i) {
                        var $item = $(this);

                        if (! $item.adRendered) {
                                XLI.AdManager.render($item, C.FEATURE_AD_CONFIG, $item.data("tagParams"));
                                $item.adRendered = true;
                        }
                });
        };

        /**
	 * Builds the HTML for a carousel slide from JSON. Expects a JSON structure like so:
	 *
	 *  {
	 *  	'title' : "Obama Administration Passes Stimulus Package",
	 *  	'category' : {
	 *  		title : 'National Politics',
	 *  		link : '/url/to/category/',
	 *  	},
	 *  	'categoryLink : "#",
	 *  	'time' : "7 minutes ago",
	 *  	'imageURL' : "/url/to/image.jpg",
	 *  	'link' : "/url/to/story/link/",
	 *		'breakingNews' : true,
	 *  	'commentCount' : "15",
	 *  	'media' : {
	 *  		'photos' : '/url/to/photos',
	 *  		'video' : '/url/to/videos'
	 *  	}
	 *		'blurb' : "A one paragraph extract of the article",
	 *		'slideWidth' : "wide"
	 *  }
         **/
        var createStorySlideFromJSON = function(json) {
		if (typeof json !== 'object' || typeof json.title !== 'string') {
			return;
		}

		// Temporary wrapper
		var $temp = $('<li></li>'),
			$actions = $('<div></div>').addClass("actions"),
			$els = {},
			cls = "";

		// Slide Image
		var addSlideImage = function() {
			var $el;
			if (json.imageURL && json.imageURL !== "") {
				try {
					$el = XLI.Builder.image({
						url : json.imageURL,
						title : json.title,
						link : json.link
					});

					if ($el) {
						$temp.append($el);
					}
				} catch(e) {
					XLI.Debug.error("Error adding slide image :" + e.message);
				}

			} else {
				cls += "noImage";
			}
		};

		// Category paragraph
		var addCategory = function() {
			var $el;
			if ((json.category && (json.category.title && json.category.title !== "")) || json.time && json.time !== "") {
				try {
					$el = XLI.Builder.categoryAndTime({
						category : {
							title : json.category.title,
							link : json.category.link
						},
						time : json.time
					});

					if ($el) {
						$temp.append($el);
					}
				} catch(e) {
					XLI.Debug.error("Error adding category paragraph :" + e.message);
				}
			}
		};

		// Title
		var addTitle = function() {
			var $el;
			if (json.title && json.title !== "") {
				try {
					$el = XLI.Builder.title({
					 	title : json.title,
					 	link : json.link,
					 	imageURL : json.imageURL,
					 	classSuffix : ""
					 }, "<h3></h3>");

					if ($el) {
						$temp.append($el);
					}
				} catch(e) {
					XLI.Debug.error("Error adding title :" + e.message);
				}
			}
		};

		// Summary / Blurb
		var addBlurb = function() {
			if (json.blurb && json.blurb !== "") {
				try {
					$els.blurb = XLI.Builder.blurb({
						txt : json.blurb,
						wordCount : (json.slideWidth === "wide") ? 40 : 15
					});

					if ($els.blurb) {
						$els.blurb.css({
							'visibility' : 'visible'
						});
						$temp.append($els.blurb);
					}
				} catch(e) {
					XLI.Debug.error("Error adding blurb :" + e.message);
				}
			}
		};

		// rating
		var addRating = function() {
			if (json.rating && json.rating !== "") {
				try {
					$els.rating = XLI.Builder.rating(json.rating);

					if ($els.rating) {
						if ($els.blurb) {
							$els.blurb.prepend($els.rating, '<br />');
						} else {
							$temp.append($els.rating);
						}
					}
				} catch(e) {
					XLI.Debug.error("Error adding blurb :" + e.message);
				}
			}
		};

		// Comments
		var addComments = function() {
			var $el;
			if (json.commentCount && json.commentCount !== "") {
				try {
					$el = XLI.Builder.comments({
						commentCount : json.commentCount,
						link : json.link
					});

					if ($el) {
						$actions.append($el);
					}
				} catch(e) {
					XLI.Debug.error("Error adding Comments :" + e.message);
				}
			}
		};

		// Media (photo / video) links
		var addMediaLinks = function() {
			var $el, mOpts = {};
			if (json.media) {
				try {
					$.each(json.media, function(key, value){
						mOpts[key] = value;
					});

					$el = XLI.Builder.mediaLinks(mOpts, "ir");

					if ($el) {
						$actions.append($el);
					}
				} catch(e) {
					XLI.Debug.error("Error adding media links :" + e.message);
				}
			}
		};

		// Do the building.
		addCategory();
		addSlideImage();
		addTitle();
		addBlurb();
		addRating();
		addComments();
		addMediaLinks();

		$temp.append($actions);

		cls += (typeof json.slideWidth === 'string' && json.slideWidth !== "") ? (" " + json.slideWidth) : "";

		return $temp.addClass(cls);
	};

        var createAdSlideFromJSON = function(data) {
                var $li = $("<li></li>").addClass("ad");

                $li.data("tagParams", data.params || {});

                return $li;
        };

	/**
	 * Activates an overlay in the homepage feature.
	 * @private
	 * @param {Object} $nav jQuery object representing one of the homepage feature nav items
	 * @param {Boolean} animate Whether or not to animate the transition.
	 * @returns nothing
	 */
	var activateSection = function($nav, animate) {
		if (typeof $nav !== 'object' || typeof $nav.jquery !== 'string' || interstitialAnimation) {
			return;
		}

		animate = (typeof animate === 'boolean') ? animate : true;

		var nav = $nav.get(0);

		try {
			// First deactivate others
			nav.$siblings.each(function(){
				var $this = $(this);
				toggleSection($this, false);
				$this.removeClass(XLI.Global.C.ACTIVE_CLASS);
				// TODO : if we're playing a video, stop or kill it.
			});
			// Then open the active one
			$nav.addClass(XLI.Global.C.ACTIVE_CLASS);
			toggleSection($nav, true, animate);

			// if we have a subnav without a preselected item, go ahead and preselect the first subnav.
			if (nav.$subnav) {
				if (!nav.$subnav.find('li.active').length) {
					nav.$subnav.find('a[href!=#]:first').trigger('click');
				}
			}

		} catch(e) {
			XLI.Debug.error('Homepage feature nav not initialized correctly. Can\'t activate section: ' + e.message);
		}
	};

	/**
	 * Animates overlays into and out of view in the homepage feature.
	 * @private
	 * @param {Object} $nav jQuery object representing one of the homepage feature nav items
	 * @param {Boolean} open true when you're opening a section, false when you're closing it.
	 * @returns nothing
	 */
	var toggleSection = function($nav, open, animate) {

		var height,
			subnavHeight,
			navWrapperEl = $e.nav.get(0),
			navListEl = $e.navList.get(0),
			navEl = $nav.get(0),
			modEl = $e.module.get(0),
			contentEl;

		animate = (typeof animate === 'boolean') ? animate : true;

		// Make note of the original dimensions of the module and nav elements
		modEl.oHeight	= modEl.oHeight || parseInt(($e.module.css('height') === 'auto') ? ($e.module.outerHeight() - parseInt($e.module.css('padding-top'), 10) - parseInt($e.module.css('padding-bottom'), 10)) : $e.module.css('height'), 10);
		modEl.vPad		= modEl.vPad || $e.module.outerHeight() - modEl.oHeight;

		navWrapperEl.top		= navWrapperEl.top || parseInt($e.nav.css('top'), 10);
		navWrapperEl.padTop		= navWrapperEl.padTop || parseInt($e.nav.css('padding-top'), 10);
		navWrapperEl.padBot		= navWrapperEl.padBot || parseInt($e.nav.css('padding-bottom'), 10);
		navWrapperEl.w 			= navWrapperEl.w || $e.nav.outerWidth();
		navWrapperEl.oHeight	= navWrapperEl.oHeight || $e.nav.height();

		//navListEl.top			= navListEl.top || parseInt($e.navList.css('top'), 10);

		try {

			if ((typeof navEl.$content !== 'undefined' && navEl.$content.length) || navEl.carousel) {

				// make note of some dimensions.
				if (typeof navEl.$content !== 'undefined' && navEl.$content.length) {
					contentEl = navEl.$content.get(0);
					contentEl.padTop = contentEl.padTop || parseInt(navEl.$content.css('padding-top'), 10);
					contentEl.padBot = contentEl.padBot || parseInt(navEl.$content.css('padding-bottom'), 10);
				}

				// tell everyone that we're animating
				interstitialAnimation = true;

				// Get the current section height.
				height = (navEl.carousel) ? modEl.oHeight : navEl.$content.outerHeight();

				if (open) {

						// Get the module height to where it needs to be.
						$e.module
							//.css({
							//	'overflow': 'hidden'
							//})
							.animate({
								'height' : (navEl.carousel) ? height : height - modEl.vPad
							}, C.SCROLL_SPEED, 'easeOutQuad');

						// Reveal the section...
						if (navEl.carousel) {
							// the carousel
								$e.carouselView
									.show()
									.css({
										'z-index' : 40
									})
									.animate({
										'opacity' : 1
									}, (C.SCROLL_SPEED / 3), 'linear', function(){
										interstitialAnimation = false;
									});
						} else {
							// An overlay
							navEl.$content
								.show()
								.css({
									'top' : height - (height * 2),
									'visibility' : 'visible',
									'z-index' : 40,
									'opacity' : 1
								});

							// Animate the content into place
							navEl.$content
								.animate({
									'top' : 0
								}, C.SCROLL_SPEED, 'easeOutQuad', function(){
								//	$e.module.css('overflow', 'visible');
									$e.document.trigger("section:openFinished");
									interstitialAnimation = false;
								});
						}

						// ...and its subnav...
						if (typeof navEl.$subnav !== 'undefined' &&
							navEl.$subnav.length &&
							typeof navEl.$subnavWrapper !== 'undefined' &&
							navEl.$subnavWrapper.length
						) {

							var snEl = navEl.$subnav.get(0);
							snEl.h = snEl.h || navEl.$subnav.outerHeight(true);

							// Set the top margin of the subnav and animate it
							navEl.$subnav
									.css({
										'top' : snEl.h - (snEl.h * 2)
									})
									.show()
									.animate({
										'top' : 0
									}, C.SCROLL_SPEED, 'easeOutQuad');


							// animate the height of the wrapper
							navEl.$subnavWrapper
									.show()
									.css({
										'height' : 0
									})
									.animate({
										'height' : snEl.h
									}, C.SCROLL_SPEED, 'easeOutQuad', function(){
										if (XLI.Global.ie6 || XLI.Global.ie7) {
											$(this).css("overflow","visible").css("height","auto").css("zoom","1");
										} else {
											$(this).css("overflow","visible").css("height","auto");
										}
									});
						}

						// ...as well as the nav elements
						$e.nav.animate({
							'height'	: (navEl.carousel) ? navWrapperEl.oHeight : height - contentEl.padTop - contentEl.padBot - navWrapperEl.padTop - navWrapperEl.padBot,
							'top'		: (navEl.carousel || (navEl.$content && navEl.$content.attr('id') === C.CALENDAR_MODULE_ID)) ? navWrapperEl.top : contentEl.padTop,
							'left'		: (navEl.$content && navEl.$content.attr('id') === C.CALENDAR_MODULE_ID) ? (navWrapperEl.w - (navWrapperEl.w * 2)) : 0
						}, C.SCROLL_SPEED, 'easeOutQuad');

//						$e.navList.animate({
//							'top'		: ((navEl.carousel || (navEl.$content && navEl.$content.attr('id') === C.CALENDAR_MODULE_ID)) ? navListEl.top : contentEl.padTop + navWrapperEl.padTop)
//						}, C.SCROLL_SPEED, 'easeOutQuad');

				} else {
					// if we're closing a section.
					// Hide the overflow so we can scroll up nicely.
					//$e.module.css('overflow', 'hidden');

					// Hide the section...
					if (navEl.carousel) {
						// the carousel
						$e.carouselView
							.css({
								'z-index' : 39
							})
							.animate({
								'opacity' : 0
							}, (C.SCROLL_SPEED / 3), 'linear', function(){
								$e.carouselView.hide();
							});
					} else {
						if (navEl.$content.attr("id") === "featuredVideos") {
							$e.document.trigger("section:close");
						}
						navEl.$content
							.css({
								'z-index' : 39
							})
							.animate({
								'opacity' : 0
							}, (C.SCROLL_SPEED / 3), 'linear', function(){
								navEl.$content.hide();
							});
							//.animate({
							//	'top' : height - (height * 2)
							//}, C.SCROLL_SPEED, 'easeInQuad'	, function(){
							//	navEl.$content.css({
							//		'visibility' : 'hidden'
							//	});
							//});
					}

					// and close its subnav
					if (typeof navEl.$subnav !== 'undefined' &&
						navEl.$subnav.length &&
						typeof navEl.$subnavWrapper !== 'undefined' &&
						navEl.$subnavWrapper.length
					) {

						var thisSnEl = navEl.$subnav.get(0);
						thisSnEl.h = thisSnEl.h || navEl.$subnav.outerHeight(true);

						// Set the top margin of the subnav and animate it
						navEl.$subnav
								.animate({
									'top' : thisSnEl.h - (thisSnEl.h * 2)
								}, C.SCROLL_SPEED, 'easeOutQuad');


						// animate the height of the wrapper
						navEl.$subnavWrapper
								.animate({
									'height' : 0
								}, C.SCROLL_SPEED, 'easeOutQuad', function(){
									navEl.$subnavWrapper.hide();
								});
					}
				}
			} else {
				if (open) {
					// We're going back to the carousel (no overlay)
					$e.module.animate({
						'height' : modEl.oHeight
					}, C.SCROLL_SPEED, 'easeInQuad', function(){
						interstitialAnimation = false;
					});
				}
			}

		} catch(e) {
			XLI.Debug.error("Couldn't activate homepage feature overlay: " + e.message);
		}
	};

	/**
	 * Adds a quickread link to a carousel slide and attaches the appropriate actions.
	 * @private
	 * @param {Object} $slide A jQuery object representing the slide to which you want to add quick read
	 * @returns nothing
	 */
	var addQuickRead = function($slide) {
		if (typeof $slide !== 'object' || typeof $slide.jquery !== 'string') {
			return;
		}

		// Construct slide data object is need be.
		var data = $slide.data('slideData') || {
			title				: $slide.find('.title').text(),
			category : {
				title	: $slide.find('.category').text(),
				link	: $slide.find('.category').attr('href')
			},
			time				: $slide.find('.time').text(),
			quickReadImageURL	: $slide.find('input[name=quickReadImageURL]').attr('value'),
			link				: $slide.find('.title a').attr('href'),
			breakingNews		: (($slide.find('.breaking').length) ? true : false),
			commentCount		: (parseInt($slide.find('.comments').text(), 10)),
			media : {
				photos	: $slide.find('.typePhoto').attr('href'),
				video	: $slide.find('.typeVideo').attr('href')
			},
			blurb				: $slide.find('.summary').text()
		};

		// Add actions links if necessary
		if (typeof data.actions === 'undefined') {
			data.actions = {};
			$slide.find('input.action[type=hidden]').each(function(){
				var $this = $(this);
				data.actions[$this.attr('name')] = $this.attr('value');
			});
		}

		$slide.data('slideData', data);


		var $links;
		var $qrLink = $slide.find('.links a');

		if($qrLink.length > 0) {
			$qrLink.bind('click', function(e){
					e.preventDefault();
					showQuickRead();
					quickReadIndex = parseInt($slide.attr('carouselindex'), 10);
					populateQuickRead(data);
					});
		} else {
			$qrLink = $('<a></a>')
					.attr('href', '#')
					.text(C.QUICK_READ_TEXT)
                                        .addClass("quickRead")
					.bind('click', function(e){
						e.preventDefault();
						showQuickRead();
						quickReadIndex = parseInt($slide.attr('carouselindex'), 10);
						populateQuickRead(data);
					});

			$links = $slide.find('p.links');
			if (!$links.length) {
				$('<p></p>')
					.addClass('links')
					.append($qrLink)
					.insertAfter($slide.find('h3'));
			} else {
				$links.prepend($qrLink);
			}
		}
	};

	/**
	 * Builds the framework HTML for the Quick Read overlay
	 * @private
	 * @returns nothing
	 */
	var buildQuickRead = function() {

		if ($e.quickRead && $e.quickRead.length) {
			return;
		}

		var HTML = {
			DIV : "<div></div>",
			SPAN : "<span></span>",
			UL : "<ul></ul>",
			LI : "<li></li>",
			A : "<a></a>"
		};

		$e.quickRead = $(HTML.DIV).attr('id', C.QUICK_READ_ID_CLASS);
		$e.quickReadContent = $(HTML.DIV)
								.addClass(C.CONTENT_CLASS)
								.appendTo($e.quickRead);

		$e.quickReadClose = $(XLI.Global.C.FLYOUT_CLOSE_HTML)
								.bind('click', hideQuickRead)
								.appendTo($e.quickReadContent);


		// Create the pager
		$e.quickReadNav = $(HTML.UL)
								.addClass(C.PAGER_CLASS)
								.appendTo($e.quickRead);

		$e.quickReadPrev = $(HTML.LI)
								.addClass(C.PREV_CLASS)
								.append(
									$(HTML.A)
										.addClass(XLI.Global.C.IR_CLASS)
										.addClass(C.PREV_CLASS)
										.text('\u2190') // Unicode left arrow
										.append(HTML.SPAN)
										.bind('click', quickReadPrev)
								)
								.appendTo($e.quickReadNav);


		$e.quickReadNext = $(HTML.LI)
								.addClass(C.NEXT_CLASS)
								.append(
									$(HTML.A)
										.addClass(XLI.Global.C.IR_CLASS)
										.addClass(C.NEXT_CLASS)
										.text('\u2192') // Unicode Right arrow
										.append(HTML.SPAN)
										.bind('click', quickReadNext)
								)
								.appendTo($e.quickReadNav);

		// Fortify IE6
		XLI.Global.ie6Hover($e.quickReadClose);
		XLI.Global.ie6Hover($e.quickReadPrev.find('span'));
		XLI.Global.ie6Hover($e.quickReadNext.find('span'));

		// Create and append the scrim
		$e.scrim = $(HTML.DIV)
						.addClass(C.SCRIM_CLASS)
						.css({
							'opacity' : 0,
							'height' : $e.module.outerHeight()
						})
						.appendTo($e.module);

		// Add the quickread element
		$e.quickRead.appendTo($e.module);
	};

	/**
	 * Loads the next carousel slide content into the quick read view. Also scrolls carousel to related slide.
	 * @private
	 * @param {Object} e Event
	 * @returns Nothing
	 */
	var quickReadNext = function(e) {
		e.preventDefault();

                var nextIndex = (quickReadIndex + 1);

                if(nextIndex > carousel.get(0).slideLength() - 1) {
                       nextIndex = 0;
                }

                // one of the items doesn't have the "data" attached because they were clone()'d
                $e.carousel.find('li[carouselindex=' + nextIndex + ']').each(function(i) {
                       var $slide = $(this);

                       if($slide.hasClass("ad") && $slide.data('tagParams') !== null) {
                               renderQuickReadAd($slide.data('tagParams'));
                       } else if($slide.data('slideData') !== null) {
                               populateQuickRead($slide.data('slideData'));
                       }
                });

                $e.carousel.find("li.ad iframe").hide();
                carousel.get(0).go(nextIndex);
		quickReadIndex = nextIndex;
	};

	/**
	 * Loads the previous carousel slide content into the quick read view. Also scrolls carousel to related slide.
	 * @private
	 * @param {Object} e Event
	 * @returns Nothing
	 */
	var quickReadPrev = function(e) {
		e.preventDefault();

                var prevIndex = (quickReadIndex - 1);

                if(prevIndex < 0) {
                       prevIndex = carousel.get(0).slideLength() - 1;
                }

                // one of the items doesn't have the "data" attached because they were clone()'d
                $e.carousel.find('li[carouselindex=' + prevIndex + ']').each(function(i) {
                       var $slide = $(this);

                       if($slide.hasClass("ad") && $slide.data('tagParams') !== null) {
                               renderQuickReadAd($slide.data('tagParams'));
                       } else if($slide.data('slideData') !== null) {
                               populateQuickRead($slide.data('slideData'));
                       }
                });

                $e.carousel.find("li.ad iframe").hide();
                carousel.get(0).go(prevIndex);
		quickReadIndex = prevIndex;
	};

	/**
	 * Displays the quick read overlay with a fade in.
	 * @private
	 * @returns nothing
	 */
	var showQuickRead = function() {
		if (!$e.quickRead || !$e.scrim) {
			buildQuickRead();
		}

                $e.carousel.find("li.ad iframe").hide();

		$e.scrim
			.show()
			.animate({
				'opacity' : 0.92
			}, C.QUICK_READ_SPEED, 'linear', function(){
				$e.module.addClass(C.QUICK_READ_ID_CLASS);
			});

		$e.quickRead
			.show()
			.css({
				'opacity' : 0
			})
			.animate({
				'opacity' : 1
			}, C.QUICK_READ_SPEED, 'linear');
	};

	/**
	 * Hides the quick read overlay with a fade out.
	 * @private
	 * @returns nothing
	 */
	var hideQuickRead = function() {
		if (!$e.quickRead || !$e.scrim) {
			return;
		}

                // Show ads because they were hidden (flickering in the carousel behind quick read)
                $e.carousel.find('iframe').show();

		$e.scrim
			.animate({
				'opacity' : 0
			}, C.QUICK_READ_SPEED, 'linear', function(){
				$e.scrim.hide();
				$e.module.removeClass(C.QUICK_READ_ID_CLASS);
			});

		$e.quickRead
			.animate({
				'opacity' : 0
			}, C.QUICK_READ_SPEED, 'linear', function(){
				$e.quickRead.hide();
			});
	};

	/**
	 * Builds the HTML for a single quick read story and populates the quick read content area.
	 * @private
	 * @param {Object} data A data structure describing the quick read information
	 * @returns nothing
	 */
	var populateQuickRead = function(data) {

		if (!data || typeof data !== 'object') {
			return;
		}

		var $els = {};

		// Clear out the previous quick read.
		emptyQuickRead();

		// Set up a wrapper for the text to function like a column
		$els.textWrap = $('<div></div>').addClass(C.WRAPPER_CLASS);

		// Image
		$els.image = XLI.Builder.image({
			url : data.quickReadImageURL,
			title : data.title,
			link : data.link
		});
		if ($els.image) {

			$els.textWrap.hide();

			var setWrapperWidth = function() {
				var w = parseInt($e.quickReadContent.css('width'), 10) - $els.image.outerWidth(true);
				$els.textWrap.css('width', w);
				if ($els.textWrap.parent().hasClass(C.SCROLL_CONTAINER_CLASS)) {
					$els.textWrap.parent().css('width', w);
				}
				$els.textWrap
					.show()
					.jScrollPane();
			};

			var imageLoadError = function() {
				// Hide the broken image
				$els.image.hide();
				// set the width to the content and show
				var w = parseInt($e.quickReadContent.css('width'), 10);
				$els.textWrap.css('width', w);
				if ($els.textWrap.parent().hasClass(C.SCROLL_CONTAINER_CLASS)) {
					$els.textWrap.parent().css('width', w);
				}
				$els.textWrap
						.show()
						.jScrollPane();
			};

			if ($els.image.get(0).tagName.toLowerCase() !== 'img') {
				$els.image = $els.image.find('img');
			}

			$els.image
				.bind('load', setWrapperWidth)
				.bind('error', imageLoadError);

			$e.quickReadContent.append($els.image);

			// In case we're looking at a cached image, IE doesn't fire the 'load' event when displaying cached images.
			if (XLI.Global.ie) {
				window.setTimeout(setWrapperWidth, 50);
			}
		}

		// Category
		$els.category = XLI.Builder.categoryAndTime({
			category : {
				title : data.category.title,
				link : data.category.link
			},
			time : data.time
		});
		if ($els.category) {
			$els.textWrap.append($els.category);
		}

		// Breaking News
		if (data.breakingNews) {
			$els.textWrap.append(XLI.Builder.breakingNews());
		}

		// Title
		$els.title = XLI.Builder.title({
		 	title : data.title,
		 	link : data.link,
		 	imageURL : data.imageURL
		});
		if ($els.title) {
			$els.textWrap.append($els.title);
		}

		// Summary / Blurb
		$els.blurb = XLI.Builder.blurb({
			txt : data.blurb
		});
		if ($els.blurb) {
			$els.textWrap.append($els.blurb);
		}

		// Actions
                $els.actions = $("<div></div>").addClass("actions");

                if($els.actions) {
                        $els.textWrap.append($els.actions);
                }

                // Comments
                $els.comments = XLI.Builder.comments({
                        commentCount : data.commentCount,
                        link : data.link
                } , '<p></p>');

                if ($els.comments) {
                        $els.actions.append($els.comments);
                }

                // Media
                $els.media = XLI.Builder.mediaLinks(data.media);
                if ($els.media) {
                        $els.actions.append($els.media);
                }

		// Some special stlying help for IE6.
		if (XLI.Global.ie6) {
			$els.actions.find('>li:first').addClass('first-child');
		}

		if ($els.actions.children().length) {
			$els.textWrap.append($els.actions);
		}

		$e.quickReadContent.append($els.textWrap);
		try {
			$els.textWrap.jScrollPane();
		} catch(e) {}


	};

	/**
	 * Renders an ad in the quick read content area
	 * @private
	 * @returns nothing
	 */
	var renderQuickReadAd = function(tagParams) {
		// Clear out the previous quick read.
		emptyQuickRead();

		XLI.AdManager.render($e.quickReadContent, C.QUICK_READ_AD_CONFIG, tagParams);

		// So we can reuse this function...
		$e.quickReadContent.get(0).adRendered = false;
	};

	/**
	 * Removes HTML from the quick read content area.
	 * @private
	 * @returns
	 */
	var emptyQuickRead = function() {
		$e.quickReadContent.find('>*:not(p.close)').remove();
	};

	return {

		/**
		 * Sets up the Feature module
		 * @public
		 * @returns nothing
		 */
		initialize : function() {
			if (initialized) {
				return;
			}

			// Create a reference to the featured module.
			$e.module = $(C.MODULE_ID);

			// And bail out if we can't find it.
			if (!$e.module.length) {
				return;
			}

			initNav();
			initCarousel();

			initialized = true;

                        // deploy the photo overlay if the hash tag contains state for it
                        if(XLI.Global.State.getHashState("fI") !== null && XLI.Global.State.getHashState("fS") !== null && XLI.Global.State.getHashState("fF") !== null) {
                                $("li#latest-photos a").eq(0).click();
                        }
		}
	};

}());

// Queue it up to load.
$(document).bind('load.featureModule', XLI.FeatureModule.initialize);
XLI.Global.queueCustomEvent('load.featureModule');



/**
	Feature Module Calendar functionality
*/

( XLI.FeatureModule.Calendar = function() {

	/**
		A Flag to keep track of whether or not we've initialized this object.
	*/
	var initialized = false;

	/**
		Options for building the filter checkboxes on the daily calendar
	 */
	var DAILY_FILTERS = {
		'xliPick'			: "ExploreLI Picks",
		'artsEnt'			: "Arts & Entertainment",
		'kidsFamily'		: "Kids & Family",
		'nightlife'			: "Nightlife",
		'sportsOutdoors'	: "Sports & Outdoors"
	};

	/**
	 *	Set Some Constants
	 */
	var CONSTANTS = {

		// The ID of the calendar module overlay
		MODULE_ID : "#featuredCalendar",

		// ID of the monthly feature section
		MONTHLY_ID : "#monthlyFeature",

		// ID of the daily listing section
		DAILY_ID : "#dailyListing",

		// Selector for grabbing the dataUrl inputs
		DATA_URL_SELECTOR : "input[name=dataUrl]",

		// Month selector list class
		MONTH_SELECTOR_CLASS : "monthSelector",

		// Daily wrapper class
		DAILY_CLASS : "daily",

		// Previous button Class
		PREV_CLASS : "prev",

		// Next button class
		NEXT_CLASS : "next",

		// Disabled class
		DISABLED_CLASS : "disabled",

		// Feature class
		FEATURE_CLASS : "feature",

		// More class
		MORE_CLASS : "more",

		// Other Events
		OTHER_EVENTS_ID : "#otherEvents",

		// Filter wrapper class
		FILTER_CLASS : "filters",

		// Filter label text
		FILTER_LABEL_TEXT : "Show",

		// View All text
		VIEW_ALL_TEXT : "View All",

		// Daily Calendar carousel selector
		DAILY_CAROUSEL_SELECTOR : "ul.carousel",

		// Date Class
		DATE_CLASS : "date",

		// Days, to be displayed in the daily calendar
		DAYS : [
			"Sun",
			"Mon",
			"Tue",
			"Wed",
			"Thu",
			"Fri",
			"Sat"
		]

	};

	/**
	 *	Element References as returned by JQuery
	 *	references created as needed
	 */
	var $elements = {

		// The calendar module
		module : null,

		// The Monthly section
		monthly : null,

		// Monthly data url input
		monthlyDataUrlInput : null,

		// Monthly Feature section
		monthlyFeature : null,

		// Monthly Other Events List
		monthlyOther : null,

		// The Month header
		monthHeader : null,

		// The Daily feature section
		daily : null,

		// Daily data url input
		dailyDataUrlInput : null,

		// Daily calendar wrapper
		dailyWrapper : null,

		// Daily calendar
		dailyCalendar : null,

		// Daily Filters
		dailyFilters : null

	};

	/**
	 *	Shorthand references to the CONSTANTS and $elements.
	 */
	var C	= CONSTANTS;
	var $e	= $elements;

	/**
	 * Initializes the monthly feature section and builds the nav to select other months
	 * @private
	 * @returns nothing
	 */
	var initMonthly = function() {
		// Find necessary elements and drop out if we don't have them.
		$e.monthly = $(C.MONTHLY_ID, $e.module);
		if (!$e.monthly.length) {
			return;
		}

		// Get some additional elements
		$e.monthlyDataUrlInput	= $e.monthly.find(C.DATA_URL_SELECTOR);
		$e.monthlyFeature		= $e.monthly.find('.' + C.FEATURE_CLASS);
		$e.monthlyOther			= $e.monthly.find(C.OTHER_EVENTS_ID + " ul");
		$e.monthHeader			= $e.monthly.find('h3');

		if (!$e.monthlyDataUrlInput.length) {
			return;
		}

		// Create the monthly navigation
		var $nav		= $('<ul></ul>')
							.addClass(C.MONTH_SELECTOR_CLASS);

		$e.monthPrev	= $('<li></li>')
							.addClass(C.PREV_CLASS)
							.addClass(C.DISABLED_CLASS + C.PREV_CLASS)
							.text(C.PREV_CLASS)
							.bind('click', getNewMonthData)
							.appendTo($nav);

		$e.monthNext	= $('<li></li>')
							.addClass(C.NEXT_CLASS)
							.text(C.NEXT_CLASS)
							.bind('click', getNewMonthData)
							.appendTo($nav);

		// Append the nav
		$nav.insertAfter($e.monthHeader);

	};

	/**
		The index of the month data is requested for
	*/
	var requestedMonth;

	/**
	 * Triggers the XHR to get additional monthly data.
	 * @private
	 * @returns nothing
	 */
	var getNewMonthData = function() {
		var $this = $(this);
		// deselect the button.
		this.blur();
		if ($this.attr('class').indexOf(C.DISABLED_CLASS) > -1) {
			return;
		}

		requestedMonth = parseInt($e.monthHeader.attr('class').replace(/^month_/, ""), 10) + ($this.hasClass('next') ? 1 : -1);
		// wrap around the year change
		if (requestedMonth > 12) {
			requestedMonth = requestedMonth - 12;
		}
		if (requestedMonth < 1) {
			requestedMonth = requestedMonth + 12;
		}

		try {
			$.ajax({
				'url'		: $e.monthlyDataUrlInput.val() + requestedMonth,
				'dataType'	: 'json',
				'success'	: updateMonthly,
				'error'		: function(xhr, message) {
					XLI.Debug.error("Request Error requesting new month data : " + message);
				}
			});
		} catch(e) {
			XLI.Debug.error("XHR Error requesting new month data : " + e.message);
		}
	};

	/**
	 * Handles a successful XHR from getNewMonthData(). Creates HTML from the JSON result
	 * @private
	 * @param {Object} data JSON describing the requested month data
	 * @returns nothing
	 */
	var updateMonthly = function(data) {
		if (!data.name || !data.featured || !data.other) {
			return;
		}

		var $els = {};

		// Empty the sections
		$e.monthlyFeature.empty();

		// update the header
		$e.monthHeader
			.text(data.name)
			.attr('class', $e.monthHeader.attr('class').replace(/\d+/, requestedMonth));

		// Build New HTML for the monthly feature
		$els.image = XLI.Builder.image({
			url : data.featured.imageUrl,
			title : data.featured.title,
			link : data.featured.link
		});

		$els.featuredDate = $('<h4></h4>').text(data.featured.date);

		$els.title = XLI.Builder.title({
			title : data.featured.title,
			link : data.featured.link
		}, '<h2></h2>');

		$els.button = XLI.Builder.button({
			txt : "Read More",
			link : data.featured.link
		});

		$.each($els, function(key, el){
			if (el) {
				$e.monthlyFeature.append(el);
			}
		});

		// Do the "Other Events" List
		$e.monthlyOther.empty();
		$.each(data.other, function(){
			if (!this.title) {
				return;
			}

			var $li	  = $('<li></li>'),
				$link = (this.link) ? $('<a></a>').attr('href', this.link).text(this.title) : false;

			if ($link) {$li.append($link);} else {$li.text(this.title);}

			$e.monthlyOther.append($li);
		});

		// Update the previous / next buttons.
		$e.monthPrev[data.prev ? 'removeClass' : 'addClass'](C.DISABLED_CLASS + C.PREV_CLASS);
		$e.monthNext[data.next ? 'removeClass' : 'addClass'](C.DISABLED_CLASS + C.NEXT_CLASS);
	};

	var dailyCarousel = null;

	var initDaily = function() {
		// Find necessary elements and drop out if we don't have them.
		$e.daily = $(C.DAILY_ID, $e.module);
		if (!$e.daily.length) {
			return;
		}

		$e.dailyWrapper			= $e.daily.find("." + C.DAILY_CLASS);
		$e.dailyCalendar		= $e.daily.find(C.DAILY_CAROUSEL_SELECTOR);
		$e.dailyDataUrlInput	= $e.daily.find(C.DATA_URL_SELECTOR);
		if (!$e.dailyDataUrlInput.length || !$e.dailyWrapper.length || !$e.dailyCalendar.length) {
			return;
		}

		// Build filters
		buildDailyFilters();

		// Initalize Carousel
		try {
			$e.dailyCalendar.jcarousel({
				scroll : 5,
				containsAds : false,
				pagerTarget : $e.daily,
				initCallback : function(carousel) {
					// Create a reference to the carousel object
					dailyCarousel = carousel;
					// Kill this init - no longer needed
					carousel.options.initCallback = null;
				},
				additionalContentBaseURL : $e.dailyDataUrlInput.val(),
				additionalContentCallback : addDays
			});
		} catch(e) {
			XLI.Debug.error("Error initializing Daily calendar carousel :" + e.message);
		}
	};

	var buildDailyFilters = function() {

		var HTML = {
			DIV		: "<div></div>",
			H5		: "<h5></h5>",
			LABEL	: "<label></label>",
			INPUT	: "<input />"
		};

		$wrap = $(HTML.DIV)
					.addClass(C.FILTER_CLASS)
					.append(
						$(HTML.H5).text(C.FILTER_LABEL_TEXT + ":")
					);

		$.each(DAILY_FILTERS, function(key, val){
			var $label = $(HTML.LABEL),
				$input = $('<input type="checkbox" checked="checked" value="' + key + '"></input>')
							.bind('change', filterDaily);

			$label
				.append($input, " " + val)
				.appendTo($wrap);
		});

		$e.dailyFilters = $wrap.find('input');

		$wrap.insertBefore($e.dailyWrapper);

	};

	var filterDaily = function() {
		if (!$e.dailyFilters.length) {
			return;
		}

		var active = [],
			selectors = {
				'on' : '',
				'off' : ''
			};

		$e.dailyFilters.each(function(){
			selectors[(this.checked) ? 'on' : 'off'] += ('dd.' + this.value + ", ");
			if (this.checked) {
				active.push(this.value);
			}
		});

		selectors.on	= selectors.on.replace(/,\s+$/, "");
		selectors.off	= selectors.off.replace(/,\s*$/, "");

		// Show and hide
		try {
			if (selectors.off !== "") {
				$(selectors.off, $e.dailyWrapper).each(function() {
					var $this 	= $(this);
					// we don't want to hide anything that still has an active class.
					for (var a in active) {
						if($this.hasClass(active[a])) {
							return;
						}
					}
					$this.hide();
				});
			}

			if (selectors.on !== "") {
				$(selectors.on, $e.dailyWrapper).show();
			}
		} catch(e) {
			XLI.Debug.error("Error filtering Daily calendar :" + e.message);
		}

	};

	var addDays = function(json) {

		if (typeof json !== 'object' || !$.isArray(json.upcoming)) {
			return;
		}

		var $els = {},
			HTML = {
				DIV		: "<div></div>",
				SPAN	: "<span></span>",
				DL		: "<dl></dl>",
				DT		: "<dt></dt>",
				DD		: "<dd></dd>",
				IMG		: "<img />",
				A		: "<a></a>"
			};

		$.each(json.upcoming, function(i, day){
			$els.temp	= $(HTML.DIV);
			$els.dl		= $(HTML.DL);
			$els.dt		= $(HTML.DT);

			var size	= parseInt(dailyCarousel.size(), 10) + 1,
				date	= new Date(day.date);

			$els.dt
				.text(C.DAYS[date.getDay()] + " ")
				.append(
					$(HTML.SPAN)
						.addClass(C.DATE_CLASS)
						.text(date.getDate())
				)
				.appendTo($els.dl);

			var buildEntry = function(data) {
				$els.dd = $(HTML.DD);
				// Add Classes
				if ($.isArray(data.categories)) {
					$.each(data.categories, function(){
						$els.dd.addClass(this);
					});
				}
				if (typeof data.imageUrl === "string" && data.imageUrl !== "") {
					// Add a featured class to this DD
					$els.dd.addClass(C.FEATURE_CLASS);
					// Add the image
					$els.image = XLI.Builder.image({
							url : data.imageUrl,
							title : data.title,
							link : data.link
						});
					if ($els.image) {
						$els.image.appendTo($els.dd);
					}
				}

				$els.title = XLI.Builder.link({
					txt : data.title,
					link : data.link
				});

				if ($els.title) {
					$els.title.appendTo($els.dd);
				}

				$els.dl.append($els.dd);

			};

			if ($.isArray(day.events)) {
				// We'll loop through the events twice,
				// first to get the first featured event (has an image)
				$.each(day.events, function(j, event){
					if (typeof event.imageUrl === "string" && event.imageUrl !== "") {
						buildEntry(event);
						return false;
					}
				});
				// then again to add any without featured events.
				$.each(day.events, function(j, event){
					if (typeof event.imageUrl !== "string" || event.imageUrl === "") {
						buildEntry(event);
					}
				});
			}

			if (day.more && day.more.count && day.more.link) {
				$els.dd = $(HTML.DD)
							.addClass(C.MORE_CLASS)
							.text(day.more.count + " more events ");

				$els.moreLink = XLI.Builder.link({
					txt : C.VIEW_ALL_TEXT,
					link : day.more.link
				});

				if ($els.moreLink) {
					$els.moreLink.appendTo($els.dd);
				}

				$els.dl.append($els.dd);
			}

			$els.temp.append($els.dl);
			dailyCarousel.add(size, $els.temp.html());

		});

		// Filter the newly added slides
		filterDaily();

	};

	return {

		/**
		 * Sets up the Feature module calendar
		 * @public
		 * @returns nothing
		 */
		initialize : function() {
			if (initialized) {
				return;
			}

			// Create a reference to the module.
			$e.module = $(C.MODULE_ID);

			// And bail out if we can't find it.
			if (!$e.module.length) {
				return;
			}

			initMonthly();
			initDaily();

			initialized = true;
		}

	};

}());

/**
	Fire it up.
*/
$(document).ready(XLI.FeatureModule.Calendar.initialize);

( XLI.VideoJsonHandler = function() {
	/*
		<li id="videoId_190">
			<div class="videoItem">
				<a href="#"><img src="/fpo/images/101x58.jpg" class="image" alt="" /></a>
				<h4><a href="#" class="category">category</a> <em class="time">5 min</em></h4>
				<p class="summary"><a href="#">title</a></p>
				<p class="meta">
					<span class="summary-long"></span>
					<span class="title"></span>
				</p>
			</div>
		</li>

		<li>
			<div class="photoItem">
				<h4><a href="#" class="category">category</a> <em class="time">5 m ago</em></h4>
				<a href="#"><img src="/fpo/images/161x92.png" class="image" alt="" /></a>
				<p class="summary"><a href="#"><?php echo $titles[rand(0, count($titles) - 1)]; ?></a></p>
			</div>
		</li>
	*/

        var count = 0;

	var ID_PREFIX = "videoId_";
	var GALLERY_PREFIX = "galleryId_";

	var HTML = {
		LI : '<li></li>',
		MAIN : '<div class="videoItem"></div>',
		IMG : '<img />',
		LINK : '<a href="#"></a>',
		CATEGORY : '<p class="info"></p>',
		CATEGORY_LINK : '<a class="category"></a>',
		TIME : '<em class="time"></em>',
		CAPTION : '<h4></h4>',
		META : '<p class="meta"></p>',
		SUMMARY_LONG : '<span class="summary-long"></span>',
		TITLE : '<span class="title"></span>',

		IMAGE_MAIN : '<div class="photoItem"></div>'
	};

	function videoItem(data) {
		var item = $(HTML.LI).attr("id", ID_PREFIX + data.videoId);
		var main = $(HTML.MAIN);
		var img = $(HTML.LINK).append($(HTML.IMG).attr("src", data.imageURL));
		var categoryLink = $(HTML.CATEGORY_LINK).attr("href", data.category.link).html(data.category.title);

		var category = $(HTML.CATEGORY).append(
			categoryLink,
			" ",
			$(HTML.TIME).text(data.time)
		);

		var caption = $(HTML.CAPTION).html(data.caption);
		var meta = $(HTML.META);
		var longSummary = $(HTML.SUMMARY_LONG).text(data.summary);
		var title = $(HTML.TITLE).text(data.title);

		meta.append(longSummary, title);

		return item.append(main.append(img, category, caption, meta));
	}

	function imageItem(data) {
                var item = $(HTML.LI).attr("id", GALLERY_PREFIX + data.galleryId);
		var main = $(HTML.IMAGE_MAIN);
		var img = $(HTML.LINK).attr("href", data.link).append($(HTML.IMG).attr("src", data.imageURL));
		var category = $(HTML.CATEGORY).append(
			$(HTML.CATEGORY_LINK).attr("href", data.category.link).html(data.category.title),
			" ",
			$(HTML.TIME).text(data.time)
		);
		var caption = $(HTML.CAPTION).html(data.title);

		var $item = item.append(main.append(img, category, caption));

		lastGalleryItemId = XLI.Global.State.getHashState("fI");

		if(lastGalleryItemId !== null && $item.attr("id") === lastGalleryItemId) {
			$item.addClass("hover");
		}

		return $item;
	}

	function item(data) {
                count++;

		if (data.videoId) {
			return videoItem(data);
		}

                if (data.imageURL) {
                        return imageItem(data);
                }

                return null;
	}

	function appendTo($container) {
		$container.append.apply($container, this);
	}

	return {
		parse : function(data) {
			var items = [];
			for (var i = 0, l = data.length; i < l; i++) {
                                var e = item(data[i]);

                                if(e === null) {
                                        continue;
				}

                                items.push(e);
			}
			items.appendTo = appendTo;
			return items;
		}
	};
}());


XLI.LatestPhotos = (function() {

       var CONSTANTS = {
               CONTAINER_SELECTOR  : "#featuredPhotos",
               SCROLLPANE_SELECTOR : ".scrollable"
       };

       var $document = $(document);
       var $container = null;
       var $scrollpane = null;

       // *** event handling ***
       var addBehaviors = function() {
               $document.bind("section:dataLoaded", photoDataLoaded);
               $document.bind("section:close", close);
       };

       var removeBehaviors = function() {
               $document.unbind("section:dataLoaded", photoDataLoaded);
               $document.unbind("section:close", close);
       };

       var photoDataLoaded = function() {
               // force jcarousel to recalculate its scrollbar heights
               $document.trigger('emchange');

               // give the jcarousel time to settle before working with it
               setTimeout(function() {
                       scrollPosition = XLI.Global.State.getHashState("fS");

                       if(scrollPosition !== null) {
                               scrollPosition = jQuery.jcarousel.intval(scrollPosition);
                               $scrollpane[0].scrollTo(scrollPosition);
                       }

			XLI.Global.State.resetHashState();
		}, 1000);

               // remove "hover" from last viewed gallery when we really hover over photo items
               var mouseoverFunction = function(e) {
                       $scrollpane.find("ul li").removeClass("hover");

                       // remove event handler from elements--we only need to run once
                       $scrollpane.find("ul li").unbind("mouseover", mouseoverFunction);
               };

               $scrollpane.find("ul li").bind("mouseover", mouseoverFunction);

               // attach event to click action--sets hash tag state upon click
               $scrollpane.find("a").click(function(e) {
                       e.preventDefault();

                       var link = jQuery(this);

                       // find our container class--it's the parent of .photoItem
                       var item = link;

                       while(! item.hasClass("photoItem")) {
                               item = item.parent();
                       }

                       item = item.parent();

                       XLI.Global.State.resetHashState();
                       XLI.Global.State.setHashState("fF", $("ul.sub li.active").attr("id"));
                       XLI.Global.State.setHashState("fI", item.attr("id"));
                       XLI.Global.State.setHashState("fS", Math.round(Math.abs($scrollpane.position().top)));
                       XLI.Global.State.syncHashState();

                       window.location.href = link.attr("href");
                });
       };

       // *** public methods ***

       var open = function() {
               $container = jQuery(CONSTANTS.CONTAINER_SELECTOR);
               $scrollpane = $container.find(CONSTANTS.SCROLLPANE_SELECTOR);

               addBehaviors();
       };

       var close = function() {
               $scrollpane.find("ul li").removeClass("hover");
       };

       return {
               open: open,
               close: close
       };
}());



/**********************************************

	Latest Videos Overlay Controller

	Call open() and this component will:

	* listen for the overlay to finish animating
	* listen for the ajax request for playlist data to finish loading
	* create html elements to display video metadata
	* create the flash player and display video metadata
	* reflect the currently playing video in the playlist
	* listen for further ajax requests for playlist data and update accordingly

	Call close() and this component will:

	* destroy the flash player
	* reset state variables
	* remove event listeners

	The events it listens for are (in addBehavior()):

	* click on video playlist thumbnails
	* section:dataLoaded on the document
	* section:openFinished on the document
	* section:close on the document

**********************************************/
( XLI.LatestVideos = function() {

	/* --- CONSTANTS --- */

	var CONSTANTS = {

		CONTAINER_SELECTOR : "#mainVideo",

		PLAYER_CONTAINER_SELECTOR : ".flash",

		VIDEOLIST_SELECTOR : "#videoList li",

		TITLE_SELECTOR : ".title",

		CATEGORY_SELECTOR : ".category",

		DURATION_SELECTOR : ".time",

		SUMMARY_SELECTOR : ".summary-long",

		COLUMN_ONE_SELECTOR : "#featuredVideos .columnOne",

		ACTIVE_CLASS : "active",

		CLOSE_BTN_SELECTOR : "#featuredVideos .close",

		SHARE_DATA_URL : "/xhr/galleries/video/share.php"

	};

	// shorthand reference
	var C = CONSTANTS;

	/* --- STATIC VARIABLES --- */

	var HTML = {
		META : '<div class="videoMeta"></div>',
		INFO : '<p class="info"></p>',
		CATEGORY : '<a></a>',
		DURATION : '<em class="time"></em>',
		TITLE : '<h2></h2>',
		SUMMARY : '<p class="summary"></p>',
		ACTIONS : '<ul class="actions"> <li><a href="#" class="fave">Add to favorites</a></li> <li><a href="#" class="friend">Send to friend</a></li> <li><a href="#" class="phone">Send to phone</a></li> </ul>',
		EXPAND : '<p class="expander"><a href="video-expanded-video.php" class="collapse">Larger Video</a></p>'
	};

	var flashvars = {
		autoPlay : false,
		showRelatedVideos: false
	};

	// dom elements
	var $document = $(document);
	var $container;
	var $columnOne;
	var $playerContainer;
	var $videoList;
	var $closeBtn;

	// generated dom elements
	var $category;
	var $duration;
	var $title;
	var $summary;
	var $actions;
	var $expand;

	// data
	var playlist = {};
	var player;
	var currentItem;
	var currentVideo;

	// state
	var initialized = false;
	var dataLoaded = false;
	var flashReady = false;
	var cubeOpen = false;
	var cubeAnimating = false;

        // Timer
        var playerLoadDelay = null;
        var retryTimer = 0;
        var retryInterval = 50; // in milliseconds
        var retryLimit = 60; // in seconds

	/* --- PUBLIC CLASS METHODS --- */

	var publicMethods = {

		open : function() {
			initialize();
			addBehavior();
			initNewData();
		},

                cleanupPlayer: function() {
                        XLI.Debug.info("XLI.LatestVideos.cleanupPlayer()");

			hideCube();

                        if (playerLoadDelay !== null) {
                                window.clearTimeout(playerLoadDelay);
                                playerLoadDelay = null;
                        }

                        if (player) {
                                player.destroy();
                                player = null;
                        }
                },

		close : function() {
			hideCube();

                        if (playerLoadDelay !== null) {
                                window.clearTimeout(playerLoadDelay);
                                playerLoadDelay = null;
                        }

                        if (player) {
                                player.destroy();
                                player = null;
                        }

			dataLoaded = false;
			flashReady = false;

			removeBehavior();
		},

		test : function() { // remove
			showCube();
		},

		test2 : function() { // remove
			hideCube();
		},

		test3 : function(e) { // rename
			showShare(e);
		},
		test4 : function() { // rename
			hideShare();
		},
		test5 : function(e) { // rename
			showEmail(e);
		},
		test6 : function() { // rename
			hideEmail();
		},

		test7 : function() { // remove
			var xyz = {};
			xyz.type = XLI.VideoPlayer.START_PREROLL;
			player.delegateEvent(xyz);
		},
		test8 : function() { // remove
			var xyz = {};
			xyz.type = XLI.VideoPlayer.END_PREROLL;
			player.delegateEvent(xyz);
		},


		test9 : function() { // remove
			var xyz = {};
			xyz.type = XLI.VideoPlayer.SHOW_HALF_LEADER;
			player.delegateEvent(xyz);
		}

	};

	/* --- PRIVATE METHODS --- */

	function initialize() {
		if (! initialized) {
			getElements();
			createMetaElements();
			initialized = true;
		}
		$playerContainer = $container.find(C.PLAYER_CONTAINER_SELECTOR);
		$playerContainer.hide();
	}

	// we can't create the player unless both the data is loaded
	// and the overlay is fully visible. this event callback manages
	// both the dataLoaded and openFinished events
	function handleAsyncEvents(event) {
		switch(event.type) {
			case "section:dataLoaded":
				initNewData();
			break;
			case "section:openFinished":
				flashReady = true;
			break;
			default:
			break;
		}
		if (dataLoaded && flashReady && ! player) {
			createPlayer();
		}
	}

	// this will only try to play the video. if the player
	// hasn't been created, nothing will happen until it is
	function initNewData() {
		$videoList = $(C.VIDEOLIST_SELECTOR);
		if ($videoList.length) {
			showVideo($videoList.eq(0),false);
			dataLoaded = true;
		}
	}

	// elements that already exist in the page
	function getElements() {
		$container = $(C.CONTAINER_SELECTOR);
		$columnOne = $(C.COLUMN_ONE_SELECTOR);
		$videoList = $(C.VIDEOLIST_SELECTOR);
		$playerContainer = $container.find(C.PLAYER_CONTAINER_SELECTOR);
		$closeBtn = $(C.CLOSE_BTN_SELECTOR);
		XLI.Global.ie6Hover($closeBtn);
	}

	// video metadata elements need to be created and appended
	function createMetaElements() {
		var meta = $(HTML.META);
		var info = $(HTML.INFO);
		$duration = $(HTML.DURATION);
		$category = $(HTML.CATEGORY);
		$title = $(HTML.TITLE);
		$summary = $(HTML.SUMMARY);
		$actions = $(HTML.ACTIONS);

		XLI.Global.ie6Hover($category);

		info.append($category, " ", $duration);
		meta.append(info, $title, $summary, $actions);
		$playerContainer.parent().after(meta);

		var sponsor = meta.siblings(".sponsor");
		if (sponsor.length) {
			meta.append(sponsor);
		}
	}

	// add the event listeners
	function addBehavior() {
		// $videoList.live("click", onVideoClick);
		$document.bind("section:dataLoaded", handleAsyncEvents);
		$document.bind("section:openFinished", handleAsyncEvents);
		$document.bind("section:close", publicMethods.close);
	}

	// remove the event listeners (don't want to try to
	// create the player when "photos" ajax data finishes
	// loading, for example)
	function removeBehavior() {
		$videoList.die("click", onVideoClick);
		$document.unbind("section:dataLoaded", handleAsyncEvents);
		$document.unbind("section:openFinished", handleAsyncEvents);
		$document.unbind("section:close", publicMethods.close);
	}

	// gets the video data from the html sent
	// over the wire and stores it the playlist object
	function parsePlaylistItem($item) {
		if (! $item.get(0)) {
			return;
		}
		var id = parseInt($item.attr("id").split("_")[1], 10);

		if (! playlist[id]) {
			playlist[id] = {
				id : id,
				category : $item.find(C.CATEGORY_SELECTOR),
				duration : $item.find(C.DURATION_SELECTOR),
				title : $item.find(C.TITLE_SELECTOR),
				summary : $item.find(C.SUMMARY_SELECTOR)
			};
		}

		return playlist[id];
	}

	// creates the player and adds an event listener to
	// go to the next video when the current one ends
	function createPlayer() {
		$playerContainer = $container.find(C.PLAYER_CONTAINER_SELECTOR);

		var vars = $.extend({}, flashvars);
		if (currentVideo) {
			vars.videoId = currentVideo.id;
		}

		player = XLI.VideoPlayer.create($playerContainer, vars);
		player.addCallback(XLI.VideoPlayer.INITIALIZE, playerReady);
		player.addCallback(XLI.VideoPlayer.COMPLETE, loadNextVideo);
		player.addCallback(XLI.VideoPlayer.START_PREROLL, showCube);
		player.addCallback(XLI.VideoPlayer.END_PREROLL, endPreroll);
//		player.addCallback(XLI.VideoPlayer.SHOW_HALF_LEADER, changeHalfLeader);
		player.addCallback(XLI.VideoPlayer.RELATED_VIDEO_CLICK, handleRelatedVideo);
		$playerContainer.show();
	}

	function playerReady() {
		$videoList.live("click", onVideoClick);
	}

	function onVideoClick(e) {
		if (! $(e.target).is(".info a")) {
			e.preventDefault();
			showVideo($(this));
		}
	}

	// can only play a video if the video player
	// has been created. otherwise the video will be the
	// first to play when it is created
	function showVideo($item,auto) {
		auto = (typeof auto === 'boolean') ? auto : true;
		currentItem = $item;
		currentVideo = parsePlaylistItem($item);
		$videoList.removeClass(C.ACTIVE_CLASS);
		$item.addClass(C.ACTIVE_CLASS);
		showMetaData();

                var videoLoader = function() {
                        if (player && player.initialized && typeof player.vars === "object") {
                                if (playerLoadDelay !== null) {
                                        window.clearTimeout(playerLoadDelay);
                                        playerLoadDelay = null;
                                }

                                try {
                                        player.setAutoPlay(auto);
                                } catch(e) {}

                                if (currentVideo.id !== player.getCurrentVideoId()) {
                                        player.loadVideo(currentVideo.id);
                                } else {
                                        if(auto) {
                                                player.play();
                                        }
                                }
                        } else {
                                if (retryTimer >= (retryLimit * 1000)) {
                                        playerLoadDelay = null;
                                        return;
                                } else {
                                        retryTimer += retryInterval;
                                        playerLoadDelay = window.setTimeout(videoLoader, retryInterval);
                                }
                        }
                };

                videoLoader();
	}

	function loadNextVideo(event) {
		if (currentItem.next("li")) {
			showVideo(currentItem.next("li"));
		}
	}

	// injects the metadata into the elements
	// below the video player
	function showMetaData() {
		$duration.html(currentVideo.duration.html());
		$category.html(currentVideo.category.html());
		$title.html(currentVideo.title.html());
		$summary.html(currentVideo.summary.html());

		// clean up any old overlays
		if (cubeOpen) {
			hideCube("now");
		}
		removeShare();
		hideEmail();
		removeHalfLeaderAd();

		$("ul.actions .fave").unbind("click").bind("click",function(e) { XLI.LatestVideos.test3(e); e.preventDefault(); });
		$("ul.actions .friend").unbind("click").bind("click",function(e) { XLI.LatestVideos.test5(e); e.preventDefault(); });
	}

	/* Resize methods (no longer used) */

	var sizes = {
		collapsed : {
			widthOne : 0,
			widthTwo : 798,
			videoHeight : 444
		},
		expanded : {
			widthOne : 173,
			widthTwo : 650,
			videoHeight : 360
		}
	};

	var collapsed = false;

	function toggleSize(e) {
		if (collapsed) {
			resize(sizes.collapsed, sizes.expanded, 1000);
		} else {
			resize(sizes.expanded, sizes.collapsed, 1000);
		}

		collapsed = !collapsed;
		$expand.find("a").html(collapsed ? "View Thumbnails" : "Larger Video").toggleClass("expand").toggleClass("collapse");

		e.preventDefault();
	}

	function resize(begin, end, duration) {

		var easing = jQuery.easing.easeInOutExpo;

		var change = {};
		for (var key in begin) {
			change[key] = end[key] - begin[key];
		}
		function animate() {
			var t = new Date().getTime() - start;
			if (t < duration) {

				$container.css("width", easing(null, t, begin.widthTwo, change.widthTwo, duration));
				$columnOne.css("width", easing(null, t, begin.widthOne, change.widthOne, duration));
				player.$container.css("height", easing(null, t, begin.videoHeight, change.videoHeight, duration));

				setTimeout(animate, 0);
			} else {

				$container.css("width", end.widthTwo);
				$columnOne.css("width", end.widthOne);
				player.$container.css("height", end.videoHeight);

			}
		}

		// run the animation
		var start = new Date().getTime();
		animate();

		// the working animation function
	}

	function endPreroll() {
		var url = player.getHalfLeaderAd();

		if (url) {
			$("#featuredVideos #mainVideo .halfBanner").html("");
			$("#featuredVideos #mainVideo .halfBanner").append("<iframe class='halfBannerIframe' style='width:234px;height:60px;border:0' height='60' width='234' scrolling='no' border='0' src='"+url+"'><a href='"+url+"'>"+url+"</a></iframe>");
		}
		hideCube();
	}

	function showShare(e) {
		if (0 === $("#featuredVideos .shareThing").length) {
			$.jsonp({
				url: C.SHARE_DATA_URL + "?callback=ws_results&videoId=" + currentVideo.id,
				callback: "ws_results",
				cache: true,
				beforeSend: function() {
					//$e.featuredVideoContainer.addClass(XLI.Global.C.LOADING_CLASS);
				},
				success: function(data) {
					//$("#featuredVideos .videoPlayer").css("position","relative").css("overflow","hidden");
					$("#featuredVideos .videoPlayer").append("<div class='shareThing'><h4>Share:</h4> <a href='#' class='close gl' onclick='XLI.LatestVideos.test4();return false;'>X<span></span></a><ul></ul></div>");

					for (i=0;i<data.length;i++) {
						$("#featuredVideos .shareThing ul").append("<li class='"+data[i].service+"'><a href='"+data[i].url+"'>"+data[i].service+"</a></li>");
					}
					$("#featuredVideos .shareThing").animate({bottom:"0"},C.SHOW_SPEED);
				},
				error : function(xhr, message) {
					XLI.Debug.error("Error getting new content for share module overlay: " + message);
				},
				complete : function() {
					//$e.featuredVideoContainer.removeClass(XLI.Global.C.LOADING_CLASS);
				}
			});
		} else {
			$("#featuredVideos .shareThing").animate({bottom:"0"},C.SHOW_SPEED);
		}
	}

	function hideShare() {
		$("#featuredVideos .shareThing").animate({bottom:"-90px"},C.SHOW_SPEED);
	}

	function removeShare() {
		$("#featuredVideos .shareThing").remove();
	}

	function showEmail(e) {
		if (0 === $("#featuredVideos .sendEmail").length) {
			//$("#featuredVideos #mainVideo").css("position","relative");
			$("#featuredVideos #mainVideo").append("<div class='sendEmail'><form action='#TBD' method='post'><fieldset><h4>Email This Video</h4><a href='#' class='close gl' onclick='XLI.LatestVideos.test6();return false;'>X<span></span></a><label for='mail_email'>email address</label><input type='text' id='mail_email' /><label for='mail_message'>message</label><textarea cols='10' rows='4' id='mail_message'></textarea><a href='' onclick='XLI.LatestVideos.test6();return false;'>send</a> <a href='' class='cancel' onclick='XLI.LatestVideos.test6();return false;'>cancel</a></fieldset></form></div>");
		}
	}

	function hideEmail() {
		$("#featuredVideos .sendEmail").remove();
	}

	function showCube() {
		var url = player.getCubeAd();

		if (url) {
			if (!cubeOpen && !cubeAnimating) {
				cubeOpen = true;
				cubeAnimating = true;
				//$("#feature").css("overflow","hidden");
				$("#featuredVideos .columnOne").css("position","relative");

				$("#featuredVideos").append("<div class='adwrapen'style='position:absolute;left:10px;top:0;width:304px;height:400px;overflow:hidden'><iframe class='adboxen' style='width:300px;height:250px;position:absolute;left:310px;top:83px;border:0' height='250' width='300' scrolling='no' border='0' src='"+url+"'><a href='"+url+"'>"+url+"</a></iframe></div");

				$("#featuredVideos .columnOne:first, #feature .main:first, #feature .nav:first").animate({left:"-305px"},1400,function() {
					XLI.Debug.log("showCube: nav animation done");
				});
				$("#featuredVideos .adboxen:first").animate({left:"0"},1400,function(){
					XLI.Debug.log("showCube: cube animation done");
					cubeAnimating = false;
				});

			} else {
				XLI.Debug.error("XLI.LatestVideos.showCube(): animation failed, cube already open;");
			}
		}
	}

	function hideCube(when) {
		XLI.Debug.log("hideCube() called");
		if (cubeOpen && !(cubeAnimating)) {
			cubeOpen = false;
			cubeAnimating = true;
			if ("now" === when) {
				$("#featuredVideos .adboxen:first").parent().remove();
				$("#featuredVideos .columnOne:first, #feature .main:first, #feature .nav:first").css("left","0");
				cubeAnimating = false;
			} else {

				$("#featuredVideos .columnOne:first, #feature .main:first, #feature .nav:first").animate({left:"1"},1400,function(){
					XLI.Debug.log("hideCube: description animation done");
				});
				$("#featuredVideos .adboxen:first").animate({left:"305px"},1400,function(){
					XLI.Debug.log("hideCube: cube animation done");
					$(this).parent().remove();
					cubeAnimating = false;
				});
			}
		} else {
			XLI.Debug.error("XLI.LatestVideos.hideCube(): animation failed, cube already hidden;");
		}
	}

	function removeHalfLeaderAd() {
		$("#featuredVideos #mainVideo .halfBanner").html("");
	}

	function handleRelatedVideo() {
		var id = player.getClickedVideoID();

		if (id) {
			XLI.VideoGalleryOverlay.load(null, id);
		}
	}

	return $.extend(publicMethods, CONSTANTS);
}());

XLI.Global.queueCustomEvent('load.activateFeatureOverlay');
