/* 
 * 
 *    / / / /_  ______ ___  ____ _____  ____ _    (_) __ \__  _____  _______  __
 *   / /_/ / / / / __ `__ \/ __ `/ __ \/ __ `/   / / / / / / / / _ \/ ___/ / / /
 *  / __  / /_/ / / / / / / /_/ / / / / /_/ /   / / /_/ / /_/ /  __/ /  / /_/ / 
 * /_/ /_/\__,_/_/ /_/ /_/\__,_/_/ /_/\__,_(_)_/ /\___\_\__,_/\___/_/   \__, /  
 *                                          /___/                      /____/ 
 * 
 * v.10.07.14
 * 
 * ----------------------------------------------
 * ---         object tree for humana         ---
 * ----------------------------------------------
 * humana
 *		.init(options)
 *		.replaced_el
 *		.replacement_el
 *		.selectify(arr,context,orig_caller)
 *		.overlay_labels(inputs)
 *		.pw_input(hidden_input,password_input)
 *		.rounder(arr)
 *		.equalize(options)
 *		.modal
 *			.init(options)
 *			.screen()
 *			.create_dialog()
 *		.compare_table
 *			.init(elem)
 *			.equalize(th)
 *			.add_x(elem)
 *			.remove_col(elem)
 *		.nav
 *			.init()
 *		.mastnav
 *			.init(arr,obj)
 *			.dropdown(index)
 *		.slideshow
 *			.timer
 *			.init(options)
 *			.control_check()
 *			.play()
 *			.fade_slide_out(elem)
 *			.fade_slide_in(elem)
 *		.tabs
 *			.init(options)
 *			.switcher(outer, nav, active, id)
 *		.carousel
 *			.init(arr)
 *			.next(trig)
 *			.prev(trig)
 *		.twitter
 *			.init(argConfig)
 *			.remove_entities(str)
 *			.linkify(str)
 *			.search(container, query)
 *		.video()
 *		.query_string(str)
 *		.maps
 *		.prepare_gmaps
 * ----------------------------------------------
 */

humana = {
	
	/* perform utility actions */ 
	init : function(options){
		if(options.overlay){
			humana.overlay_labels(options.overlay);
		}
		if(options.round){
			humana.rounder(options.round);
		}
		if(options.equalize){
			$(options.equalize).each(function(){
				humana.equalize(this);
			});
		}
		
		/* onload handlers */
		
		// product list expandable
		$('.product_list').delegate('.items>li', 'hover', function(e){
			e.preventDefault();
			$(this).toggleClass('hover');
		});
		$('.product_gallery').delegate('.items>li', 'hover', function(e){
			e.preventDefault();
			$(this).toggleClass('hover');
		});
		
		// tabbed module behaviors
		$('ul.tabs li').each(function(){
			if(!$(this).hasClass('active')){
				var currContent = $(this).find('a').attr('href');
				$(this).closest('ul').next('.tabs_container').find(currContent).hide();
			}
		});
		$('ul.tabs').delegate('li', 'click', function(e){
			e.preventDefault();
			if($(this).hasClass('active')){
				return false;
			} else {
				var currContent,
					newContent;
				currContent = $(this).closest('ul.tabs').find('li.active a').attr('href');
				$(this).closest('ul').next('.tabs_container').find(currContent).hide();
				$(this).closest('ul.tabs').find('li.active').toggleClass('active');
				newContent = $(this).find('a').attr('href');
				$(this).closest('ul').next('.tabs_container').find(newContent).show();
				$(this).addClass('active');
			}
		});
		// test change 8/28/2010 - 3pm turn
		
		// new window link & external domain link handler
		$('body').delegate('a[rel="external"], a.new_window', 'click', function(e){
			e.preventDefault();
			window.open($(this).attr('href'));
		});
		
		// external link detection hack - remove after augmenting build tool to convert these
		var intLinkRE = /^\/|^http\:\/\/www.humana.com|^http\:\/\/humana.com|^\s*#|^https\:\/\/securedlogons.humana.com|^.*espanol.humana.com|^http\:\/\/test-www2.humana.com|^http\:\/\/qa-www2.humana.com/i,
			docLinkRE = /\?file=/;
		$('body a').each(function(){
			if(!intLinkRE.test($(this).attr('href'))){
				$(this).attr('rel', 'external');
			}
			if(docLinkRE.test($(this).attr('href'))){
				$(this).addClass('pdf');
			}
		});	
		
		// medicare zip code search binding
		$('body').delegate('#medicare_plans_search', 'submit', function(e){
			e.preventDefault();
			window.open($(this).attr('action')+'?'+$(this).serialize());
		});
		
		// humana one state dropdown binding
		$('body').delegate('#individual_plans_search', 'submit', function(e){
			e.preventDefault();
			window.open($(this).attr('action')+'?'+$(this).serialize());
		});
		
		// alternating table.data row classes
		if($('table.data').length > 0){
			$('table.data tr:even').addClass('alt');
		}
		
	},
	
	
	/* global storage for element replacements using selectify */
	replaced_el : '',
	replacement_el : '',
	
	/* utility method for transforming list(s) into select(s)
	 * - arr = array of jQuery collections containing lists to be selectified.
	 * - context should be passed as null
	 * - origCaller should be passed as arguments.callee from a calling function.
	 * - EXAMPLE OF HOW TO CALL:
	 * - if($('.pulldown').length > 0){ humana.selectify([$('.pulldown')], null, arguments.callee); }
	 */
	selectify : function(arr, context, origCaller){
		var tmpAttrs = [],
			tmpClone,
			newEl;

		$(arr).each(function(){

			// store the original element so we can extract its stuff later
			tmpClone = $(this).clone();

			// perform element arrangement, based on where in the list's node tree we are
			if(tmpClone.is('ul') || tmpClone.is('ol') || tmpClone.is('dl')){
				newEl = $('<select></select>');
				humana.replaced_el = $(this);
				humana.replacement_el = newEl;
			} else {
				if(context !== undefined && context.is('select')){
					context.append('<option></option>');
					newEl = context.find('option:last');
					if(tmpClone.get(0).firstChild.nodeType == 3){ /* 3 == Node.TEXT_NODE - babysit IE */
						newEl.text(tmpClone.text());
					}
				} else if(context !== undefined && context.is('option')){
					if(tmpClone.is('a')){
						context.text(tmpClone.text());
						context.val(tmpClone.attr('href'));
					} else {
						context.append(tmpClone);
					}
					newEl = tmpClone;
				}
			}

			if(tmpClone !== newEl){
				// dump list's attributes to a tmp var
				tmpAttrs = tmpClone.get(0).attributes;

				$(tmpAttrs).each(function(){
					if(this.nodeName == 'class'){
						newEl.addClass(this.nodeValue);
						if(this.nodeValue == 'heading'){
							newEl.attr('disabled','disabled');
						} else if(this.nodeValue == 'current'){
							newEl.attr('selected','selected');
						}
					} else {
						if(this.nodeValue !== null && this.nodeValue !== ''){
							newEl.attr(this.nodeName, this.nodeValue);
						}
					}
				});

				// artificially limit depth of traversal by cutting context off after <option> el's in the node tree
				if(!newEl.is('select') && !newEl.is('option')){
					newEl = undefined;
				}
				// recursively call selectify, passing array of list children to process and current new element for context
				if(tmpClone.children().length > 0){
						humana.selectify(tmpClone.children(), newEl);
				}
			}

		});

		// if we're done with all the recursion, perform the actual replacement.
		if(humana.selectify.caller === origCaller){
			humana.replaced_el.replaceWith(humana.replacement_el);
			// select box binding for triggering page change
			// - using .change() here rather than .delegate() in global init due to ie6 weirdness
			$('.pulldown, .condense').change(function(e){
				location.href = $(this).val();
			});
		}
	},
	
	/* label overlay util method */
	overlay_labels : function(inputs) {
		inputs.each(function() {
			$(this).prev('label')
				.hide()
				.end()
				.val($.trim($(this).prevAll('label:first').text()));
		});
		inputs.bind('focus', function() {
			if($.trim($(this).val().toLowerCase()) == $.trim($(this).prevAll('label:first').text().toLowerCase())) {
				$(this).val('');
			}
		}).bind('blur', function() {
			if($(this).val() == '') {
				$(this).val($.trim($(this).prevAll('label:first').text()));
			}
		});
	},
	
	/* facebook-style password input switcher */
	pw_input : function(hidd, pass){
		
		pass.hide();
		hidd.show();
		humana.overlay_labels(hidd);
		
		$(hidd).focus(function(){
			$(this).hide();
			$(pass).show()
				.focus();
		});
		
		$(pass).blur(function(){
			if(this.value == ''){
				$(hidd).show();
				humana.overlay_labels(hidd);
				$(this).hide();
			}
		});
		
	},
	
	/* corner rounding util method */
	rounder : function(arr){
		$(arr).each(function(){
			$(this).addClass('rounded')
				.before('<span class="left"></span>')
				.after('<span class="right"></span>');
		});
	},
	
	/*
	 * equalize column heights for display util method
	 *
	 * cols - jQuery collection containing column elements to equalize
	 * type - String value either 'simple' or 'multi'
	 *	- if 'simple', two cols, set height to taller value
	 *	- if 'multi', multiple rows in each column, combine and then set height to tallest
	 * example options object: {cols:$('#mycols),type:'simple'}
	 */
	equalize : function(options){
		var cols = options.cols,
			type = options.type,
			tallest = 0,
			totalLeftHeight = 0,
			totalRightHeight = 0,
			heightExtras = 0,
			filterFloat,
			newHeight;
			
		if(type == 'simple'){
		
			cols.each(function(){
				if(parseInt($(this).height(), 10) > tallest){
					tallest = parseInt($(this).height(), 10);
				}
			});
			cols.css('height', tallest);
			
		} else if(type == 'multi'){		
				
			cols.each(function(cnt, elem){
				if($(this).css('float') == 'left'){
					if(cnt === 0){
						heightExtras += parseInt($(this).css('margin-bottom'), 10);
						totalLeftHeight += heightExtras;
					}
					totalLeftHeight += parseInt($(this).height() +
									parseInt($(this).css('padding-bottom'), 10) +
									parseInt($(this).css('border-bottom-width'), 10), 10);
				} else if($(this).css('float') == 'right'){
					totalRightHeight += parseInt($(this).height(), 10);
				}
			});

			if(totalLeftHeight > totalRightHeight){
				filterFloat = 'right';
				newHeight = totalLeftHeight;
			} else if(totalRightHeight > totalLeftHeight){
				filterFloat = 'left';
				newHeight = totalRightHeight;
			} else {
				filterFloat = 'right';
				newHeight = totalLeftHeight;
			}

			cols.each(function(){
				if($(this).css('float') == filterFloat){
					$(this).css('height', newHeight);
				}
			});
		}
	},
	
	/*
	 * modal dialog utility
	 *
	 * simple modal dialog popper.  for accessibility uses existing inline elements on page
	 * via provided jQuery collection to populate the dialog.
	 * - these elements should be hidden via JS in their own handlers, so that modern clients don't see the originals.
	 * - we clone the hidden original and populate the dialog with the copy.  the original is untouched.
	 */
	modal : {
	
		// initialize modal dialog window
		// - we do a bit more work here than normal to make sure that everything needed is in 
		// - place and kosher, to keep from popping empty windows or grinding and causing poor responsiveness.
		// - as a bonus, the function handles most predictable input-type scenarios.
		init : function(options){
			var tmp;
		
			if(typeof(options) != "object" && $(options).length < 1){
				
				// fail silently (but with honor), like a ninja.
				return false;
			
			} else if( typeof(options) == "object" && options.jquery === undefined ){
			
				// parse out options object
				// - if options is expanded in the future, here is the spot to process it.
				// - for now, options.elem is all we're using.  see associated conditionals below.
				
				if(options.elem !== undefined && options.elem.jquery !== undefined){
				
					// we've been given a jQuery object.  ideal!
				
				} else if(options.elem !== undefined){
				
					if($(options.elem).length < 1){
						return false;
					} else {
						options.elem = $(options.elem);
					}
					
				}
				
			} else if(options.jquery !== undefined){
				
				// jquery in the house
				if(options.elem === undefined){
					tmp = options;
					options = {};
					options.elem = tmp;
				}
				
			} else if($(options).length < 1){
				
				return false;
			
			} else {
				tmp = options;
				options = {};
				options.elem = $(tmp);
			}
			
			// if we made it here, we know that by hook or by crook... options.elem is now a valid jQuery object.
			humana.modal.create_dialog(options.elem);
		},
		
		// utility for toggling transparent overlay behind modals
		screen : function(){
			// bind event for removal
			$('#modal_screen').live('click', function(e){
				e.preventDefault();
				$('#dialog').remove();
				$(this).remove();
			});
				
			// check for existing, render out
			if($('#modal_screen').length < 1){
				$('body').append('<div id="modal_screen"></div>');
				$('#modal_screen').animate({opacity:0.75,height:$(window).height()}, 600);
			} else if(!$('#modal_screen').is(':visible')){
				$('#modal_screen').animate({opacity:0.75,height:$(window).height()}, 600);
			} else {
				$('#modal_screen').fadeOut();
			}
		},
		
		// create dialog box
		create_dialog : function(elem){
			humana.modal.screen();
			
			if($('#dialog').length < 1){
				$('body').append('<div id="dialog"><div class="content"></div></div>');
			} else if(!$('#dialog').is(':visible')){
				$('#dialog').fadeIn();
			}

			// initialize with 1/20th viewport-width margin on all sides
			var xGap = Math.floor($(window).height() / 20),
				yGap = Math.floor($(window).width() / 20),
				widthTmp = parseInt(yGap * 18, 10),
				heightTmp = parseInt(xGap * 18, 10);
			$('#dialog').css({
				'left':yGap,
				'top':xGap,
				'width':widthTmp,
				'height':heightTmp
			});
			
			// populate dialog
			elem.clone().appendTo('#dialog .content');
			
			// trick to help compare_table dialogify function
			return $('#dialog .content');
		}
	
	},
	
	/* compare table utility */
	compare_table : {
		
		// initialize table functionality using provided element
		init : function(elem){
			var th = elem.find('th');
			
			// hide table so we can modalize it
			elem.hide();
			
			humana.compare_table.equalize(th);
		},
		
		// equalize column widths
		equalize : function(th){
			var width = Math.floor(100 / parseInt(th.length, 10));
			th.css('width',width+'%');
		},
		
		// add 'x' buttons to provided column(s)
		add_x : function(elem){
			elem.prepend('<a class="x_btn" href="#" title="Close">X</a>')
				.find('.x_btn')
				.live('click', function(){
					humana.compare_table.remove_col(elem);
				});
		},
		
		// remove column given provided TH element
		remove_col : function(elem){
			var col = elem.index(),
				table = elem.closest('table'),
				tmpEl;
				
			elem.remove();
			table.find('tr').each(function(){
				tmpEl = $(this).find('td')
					.get(col);
				$(tmpEl).remove();
			});
			
			humana.compare_table.equalize(table.find('th'));
		},
		
		// perform the functions necessary to pop a dialog and put our table into it
		dialogify : function(elem){
			var table = humana.modal.create_dialog(elem).find('table'),
				th;
			
			table.show();
			th = table.find('th');
			th.each(function(){
				humana.compare_table.add_x($(this));
			});
		}
		
	},
	 
	/* nav object */
	nav : {
		
		// initializes the nav submenus
		init : function(){
			$('#nav_primary').find('.submenu .content')
				.css({'border-bottom':'0'})
				.after('<img class="submenu_btm" src="/library/images/nav_menu_btm.png" alt="" width="639" height="43" />');
		}
		
	},
	
	/* mastnav object
	 * - initialize with object containing index of mastnav elements to activate dropdown for,
	 * - as well as object containing dropdown data in format like:
	 * - {0:[{title:item1title,url:item1url},{title:item2title,url:item2url}],2:[{title:item1title,url:item1url}]}
	 */
	mastnav : {
	
		// initialize dropdowns
		init : function(arr, obj){
			// attach data to DOM elements for activated items so we can find them later
			var linkArr = $('#masthead ul li a');
			$(arr).each(function(){
				linkArr.eq(parseInt(this)).data('mastnav', this);
			});
			
			// store active item array and dropdown object for later use
			humana.mastnav.activeArr = $(linkArr);
			humana.mastnav.dropdownData = obj;

			// event handler for dropdowns
			$('#masthead').delegate('ul li a', 'click', function(e){
				if($(this).data('mastnav')){
					e.preventDefault();
					humana.mastnav.dropdown(parseInt($(this).data('mastnav')));
				}
			});
			$('#masthead').delegate('ul li div.mastdrop', 'mouseleave', function(){
				// hide dropdown if it exists
				$(this).hide();
			});
		},
		
		// trigger dropdown menu for given index
		dropdown : function(index){
			var self = humana.mastnav.activeArr.eq(index),
				dropDiv = '<div id="mastdrop-'+index+'" class="mastdrop"></div>';
			if(self.next('div').length == 0){
				self.after(dropDiv);
				var thisDrop = self.next('div');

				if(thisDrop.prev('a').text() !== 'Log In'){
					// append links from data object unless we're dealing with LogIn link
					thisDrop.append('<ul></ul>');
					var itemMarkup;
					for(var i = 0; i < humana.mastnav.dropdownData[index].length; i++){
						if(i == 0){
							itemMarkup = '<li class="first"><a href="'+humana.mastnav.dropdownData[index][i].url+'">'+humana.mastnav.dropdownData[index][i].title+'</a></li>';
						} else if(i == humana.mastnav.dropdownData[index].length - 1){
							itemMarkup = '<li class="last"><a href="'+humana.mastnav.dropdownData[index][i].url+'">'+humana.mastnav.dropdownData[index][i].title+'</a></li>';
						} else {
							itemMarkup = '<li><a href="'+humana.mastnav.dropdownData[index][i].url+'">'+humana.mastnav.dropdownData[index][i].title+'</a></li>';
						}
						thisDrop.find('ul').append(itemMarkup);
					}
					thisDrop.show();					
				} else {
					// build out login form
					var loginFormMarkup = '<form action="https://securedlogons.humana.com/common/scripts/PreLogin.asp" id="mast_login" method="post">'
											+'<fieldset>'
											+'<legend>log in</legend>'
											+'<label for="mast_uid">User ID</label>'
											+'<input id="mast_uid" type="text" name="Userid" />'
											+'<label for="mast_password">Password</label>'
											+'<input id="mast_password" name="" type="text" />'
											+'<input id="mast_password-actual" name="txtPassword" type="password" />'
											+'<input type="hidden" name="launchURL" />'
											+'<input type="hidden" name="slstylesheet" />'
											+'<input type="hidden" name="portoforigin" value="0" />'
											+'<input type="hidden" name="sourcesite" value="1" />'
											+'<button name="login" type="submit"><span>Log In</span></button>'
											+'<a href="https://securedlogons.humana.com/common/scripts/UserIDPasswordHelp.asp" id="mast_forgot_password" title="Forgot ID/Password?">Forgot ID/Password?</a>'
											+'</fieldset>'
											+'</form>';
					thisDrop.append(loginFormMarkup);
					humana.pw_input($('#mast_password'),$('#mast_password-actual'));
					humana.overlay_labels($(thisDrop).find('input[type="text"]'));
					thisDrop.show();
				}
			} else {
				self.next('div').show();
			}
		}
		
	},
	
	/* slideshow object */
	slideshow : {
		
		timer : '',
		
		// initializes the slideshow and its methods
		init : function(options){
			humana.slideshow.id = options.id;
			if(options.controls === true){
				humana.slideshow.controls = true;
				var html_controls = '<p id="slideshow_nav">';
				var counter = 1;
				$(humana.slideshow.id+" .slide").each( function(){
					if (counter == 1)
						html_controls += '<a id="slide'+counter+'_link" href="#slideshow" class="active">'+counter+'</a>';
					else
						html_controls += '<a id="slide'+counter+'_link" href="#slideshow">'+counter+'</a>';
					counter++;
				});
				html_controls += '<span id="control" href="#slideshow">></span></p>';
				$(humana.slideshow.id).append(html_controls);
			} else {
				humana.slideshow.controls = false;
			}
			
			// bind control elements
			$('#slideshow_nav #control').click(function(e){
				e.preventDefault();
				if($(this).hasClass('active')) {
					humana.slideshow.play();
				}	else {
					$.clearTimer(humana.slideshow.timer);
				}
			});
			$('#slideshow_nav a').click(function(e){
				e.preventDefault();
				if(!$(this).hasClass('active')){
					var curr = $(humana.slideshow.id + ' > .active');
					humana.slideshow.fade_slide_out($(curr));
					humana.slideshow.fade_slide_in($('#' + $(this)[0].id.replace('_link', '')));
					if(!$('#slideshow_nav #control').hasClass('active')){
						$.clearTimer(humana.slideshow.timer);
					}
				}
			});
			
			// kickoff slideshow
			if($(humana.slideshow.id).length > 0){
				humana.slideshow.timer = $.timer(6000, function(){
					humana.slideshow.play();
				}, function(){
					if(humana.slideshow.control_check()){
						$('#slideshow_nav #control').toggleClass('active');
					}
				});
			}
		},
		
		// checks if the control elements have been enabled
		control_check : function(){
			return humana.slideshow.controls ? true : false;
		},
		
		
		// triggers the slideshow
		play : function(){
			var controller = $('#slideshow_nav #control'),
				curr;
			
			if(humana.slideshow.control_check()){
				if(controller.hasClass('active')){
					controller.toggleClass('active');
				}
			}
			
			curr = $(humana.slideshow.id + ' > .active');
			
			humana.slideshow.fade_slide_out(curr);
			
			if($(curr).next('.slide').length > 0){
				humana.slideshow.fade_slide_in($(curr).next('.slide'));
			} else {
				humana.slideshow.fade_slide_in($(humana.slideshow.id + ' .slide:first'));
			}
			
			humana.slideshow.timer = $.timer(8000, function(){
				humana.slideshow.play();
			}, function(){
				if(humana.slideshow.control_check()){
					$('#slideshow_nav #control').toggleClass('active');
				}
			});
		},
		
		// fade out current slide
		fade_slide_out : function(elem){
			$(elem).fadeOut(1200)
				.toggleClass('active');
			if(humana.slideshow.control_check()){
				$('#' + elem[0].id + '_link').toggleClass('active');
			}
		},
		
		// fade in new slide
		fade_slide_in : function(elem){
			$(elem).fadeIn(1200)
				.toggleClass('active');
			if(humana.slideshow.control_check()){
				$('#' + elem[0].id + '_link').toggleClass('active');
			}
		}
		
	},
	
	/* tabs object
	 * - init with object containing id, like {id:'#tabset'}
	 */
	tabs : {
	
		// enable tab behaviors on provided outer id
		init : function(options){
			var outer = $(options.id),
				nav = $(options.id + '_nav'),
				active = $(nav).find('li.active'),
				visible = $(active.find('a').attr('href'));
			
			outer.find('.tab').css({'position':'absolute','top':'0'});
			outer.find('.tab').not(visible).hide();
			
			// bind tab-switching behaviors for tab nav
			nav.find('li').bind('click', {outer:outer,nav:nav}, function(e){
				e.preventDefault();
				var active = $(nav).find('li.active'),
					id = parseInt($(this).find('a').attr('href').replace('#tab', ''), 10) - 1;
				humana.tabs.switcher(outer, active, nav, id);
			});
		},
		
		// switch away from provided active tab, to tab in provided outer container's tabset_nav with provided id
		switcher : function(outer, active, nav, id){
			active.toggleClass('active');
		
			var curr = nav.find('li').eq(id),
				visible = curr.find('a').attr('href');
			
			curr.toggleClass('active');
			
			outer.find('.tab').not(visible).fadeOut(600);
			$(visible).fadeIn(600);
		}
	
	},
	
	/* carousel object */
	carousel : {
	
		// enable carousel behaviors on supplied jQuery objects
		init : function(arr){
			$(arr).each(function(){
				$(this).before('<a class="carousel_left_arrow" href="#">prev</a>')
					.after('<a class="carousel_right_arrow active" href="#">next</a>');

				$(this).prev()
					.bind('click', function(e){
						e.preventDefault();
						humana.carousel.prev($(this));
					})
					.end()
					.next()
						.bind('click', function(e){
							e.preventDefault();
							humana.carousel.next($(this));
						});
			});
		},
		
		// advance the carousel one slide, triggering button passed in for context
		next : function(trig){
			var curr = trig.prev().find('.carousel_item.active'),
				nxt = curr.next('.carousel_item');

			if(nxt.length == 0){ 
				nxt = $('.carousel_item:first');
			}
							
			curr.hide().toggleClass('active');
			nxt.show().toggleClass('active');
		},
		
		// retreat the carousel one slide, triggering button passed in for context
		prev: function(trig){
			var curr = trig.next().find('.carousel_item.active'),
				prv = curr.prev('.carousel_item');
			
			if (prv.length == 0) {
				prv = $('.carousel_item:last');
			}
			
			curr.hide().toggleClass('active');
			prv.show().toggleClass('active');
		}
		
	},
	
	/* twitter widget */
	twitter : {
		
		// initialize widget with object containing configuration details
		// - REQUIRED: 'search' Array of Objects containing: container: (String) ID of container, query: (String) query
		init : function(argConfig){

			// set defaults to be overwritten by user config...	
			var defaultConfig = {
					// lang passed straight through to twitter, filters results
					lang: "en",
					// results per page
					rpp: "5",
					// number of pages to return
					page: "1",
					// avatarsize in pixels
					avatarsize: "48",
					// url shouldn't need to change
					url: "http://search.twitter.com/search.json"
				},
				// then perform overloading of object.
				emptyConfig = {};
				this.config = $.extend(true, emptyConfig, defaultConfig, argConfig);

				// trigger search for each provided search object
				$(this.config.search).each(function(){
					humana.twitter.search(this.container, this.query);
				});
		},
		
		// remove html entities from strings
		remove_entities : function(str){	
			var tmp = $("<div class=\"twitterTmp\"></div>")
						.appendTo("body")
						.css("display", "none")
						.html("<textarea>" + str + "</textarea>")
						.children("textarea")
							.val();
			$(".twitterTmp").remove();
			return tmp;
		},
		
		// linkify appropriate strings within tweet
		linkify : function(str){
			var urlRE = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi,
				usernameRE = /[\@]+([A-Za-z0-9-_]+)/gi,
				hashtagRE = /[\#]+([A-Za-z0-9-_]+)/gi;

			str = str.replace(urlRE, "<a href=\"$1\">$1</a>");
			str = str.replace(usernameRE, "<a href=\"http://twitter.com/$1\" title=\"$1\">@$1</a>");
			str = str.replace(hashtagRE, "<a href=\"http://search.twitter.com/search?q=&tag=$1\">#$1</a>");
			return str;
		},
		
		// search twitter for query supplied as argument, insert results into container (format "#id")
		search : function(container, query){
			query = escape(query);
			
			var searchUrl = this.config.url +
							"?q=" + query +
							"&rpp=" + this.config.rpp +
							"&page=" + this.config.page +
							"&lang=" + this.config.lang +
							"&callback=?";
							
			$.ajax({
				url: searchUrl,
				type: "GET",
				dataType: "json",
				success: function(data, textStatus){
					var htmlToAppend = "";
					$.each(data.results, function(i, item){
						htmlToAppend += humana.twitter.linkify(item.text);
					});
					
					$(container).append(htmlToAppend);
				}
			});
		}	
	},
	
	/* video player initialization */
	video : {
		
		init : function(){
			if($('#player').length > 0){
				// load video player script
				$.getScript('/library/scripts/flowplayer-3.2.0.min.js', function(){
					// trigger player
					// TODO: switch SWF to humana domain
					flowplayer("player", 
						{ src:'/library/players/flowplayer.commercial-3.1.5.swf', 
							wmode: 'opaque'
						}, 
						{	key: '#@631e85cf531f300280c', 
							logo: null
					});	
				});
				
			}
		}
		
	},
	
	/* querystring parsing utility */
	query_string : function(str){
		var qsd = {},
			tmp = [],
			qs,
			pairs = [];
		
		tmp = str.split('?');
		qs = decodeURI(tmp[1]);
		
		if(!qs){
			return;
		}
		
		qs = qs.substring(1);
		pairs = qs.split('&');
		
		for(var i=0; i<pairs.length; i++){
			var kvp = pairs[i].split('=');
			qsd[kvp[0]] = kvp[1];
		}
		
		return qsd;
	},
	
	/* define object global for maps array */
	maps : [],
	
	prepare_gmaps : function(){
		$(".gmap").each(function(i){
			$(this).after('<div id="gmap'+i+'" class="gmap" style="width: 330px; height: 220px;"></div>');
			var coords = $.getAllQueryStrings({URL: $(this).attr("href")}).sll.split(',');
			var latlng = new google.maps.LatLng(coords[0],coords[1]);
	    var myOptions = {
	      zoom: 16,
	      center: latlng,
				mapTypeControl: true,
				mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
	      mapTypeId: google.maps.MapTypeId.ROADMAP
	    };
	    var map = new google.maps.Map(document.getElementById('gmap'+i), myOptions);
			var marker = new google.maps.Marker({
				position: latlng, 
				map: map
			});
			$(this).remove();
		});
		
	},
	
	medicare_alert : function() {
		//$.getScript("/library/scripts/jquery.tools.min.js");
		//$.getScript("/library/scripts/jquery.url.min.js");
		//if ($("#page_wrapper.medicare a").length > 0) {
//			var modalHTML = ''
//			  + '<div class="modal" id="leavingmedicare" align="center">'
//				+ '	<img src="/library/images/logo_humana.gif" id="logo_primary" alt="HUMANA - Guidance when you need it most" />'
//				+ '	<h2>You are leaving the Medicare section<br> of this Website.</h2><br />'
//				+ '	<div class="modal_buttons">'
//				+ '		<a href="#" class="close back" id="modal_back">Go Back</a>'
//				+ '		<a href="#" class="continue button" id="modal_continue" title="Continue"><span>Continue</span></a>'
//				+ '	</div>'
//				//+ '	<input id="optout" name="optout" type="checkbox" value="Do not display this message again." /> <label for="optout">Do not display this message again.</label>'
//				+ '</div>';
//			$("body").append(modalHTML);
//			
//			$("#page_wrapper.medicare a").live("click", function(e) {
//				e.preventDefault();
//				var destUrl = $(this).attr("href");
//				var currentUrl = $(this).attr("host");
//				var triggers = $(".modal").overlay({
//					mask: {
//						color: '#000000',
//						loadSpeed: 200,
//						opacity: 0.5
//					},
//					oneInstance: false,
//					closeOnClick: false
//				});
//				var buttons = $(".modal a").click(function(e) {
//					if ($(this).hasClass("continue")) {
//						//if ($("#optout").isChecked())
//						//setModalCookie();
//						document.location = destUrl;
//					}
//					if ($(this).hasClass("back"))
//						triggers.eq(3).overlay().close;
//				});
//				if (!checkDestination(destUrl)) {
//					triggers.load();
//				} else {
//					document.location = destUrl;
//				}
//			});
//			
//			function checkDestination(url) {
//				var currentURL = {
//					"url" : window.location,
//					"host" : jQuery.url.attr("host"),
//					"folder" : jQuery.url.segment(1)
//				};
//				if (url.substr(0,4) != "http") url = "http://"+currentURL.host+url;
//				var destURL = {
//					"url" : url,
//					"host" : jQuery.url.setUrl(url).attr("host"),
//					"folder" : jQuery.url.setUrl(url).attr("directory").split('/')
//				};
//				jQuery.url.setUrl(currentURL.url);				
//				if (currentURL.host != destURL.host) {
//					return false;
//				} else {
//					if (destURL.folder[1].toLowerCase() != "medicare") {
//						return false;	
//					}
//				}
//				return true;
//			}
//		}
//		function setModalCookie() {
//			var expires = new Date();
//			expires.setDate(expires.getDate()+14);
//			document.cookie = "HumMedicareModal=No;expires=" + expires.toUTCString();
//		}
//		function getModalCookie(key) {
//			if (document.cookie.length > 0) {
//				start = document.cookie.indexOf(key+"=");
//				if (start != -1) {
//					start = start + key.length+1;
//					end = document.cookie.indexOf(";",start);
//					if (end==-1) {
//						end = document.cookie.length;
//						return unescape(document.cookie.substring(start,end));
//					}
//				}
//			}
//			return "";
//		}
//		function checkModalCookie() {
//			return getModalCookie("HumMedicareModal");
//		}
	}
		
};

/*
 * jQuery Timer Plugin
 * http://www.evanbot.com/article/jquery-timer-plugin/23
 *
 * @version      1.0
 * @copyright    2009 Evan Byrne (http://www.evanbot.com)
 */ 

jQuery.timer = function(time,func,callback){
	var a = {timer:setTimeout(func,time),callback:null};
	if(typeof(callback) == 'function'){
		a.callback = callback;
	}
	return a;
};

jQuery.clearTimer = function(a){
	clearTimeout(a.timer);
	if(typeof(a.callback) == 'function'){
		a.callback();
	}
	return this;
};

/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
 * $Rev: 2446 $
 *
 * Version 2.1.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE6 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

})(jQuery);

