(function($) {

$.fn.tweet = function(o){
var s = {
  username: ["metricameasures"],                // [string]   required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"]
  list: null,                               // [string]   optional name of list belonging to username
  avatar_size: null,                        // [integer]  height and width of avatar if displayed (48px max)
  count: 6,                                 // [integer]  how many tweets to display?
  intro_text: null,                         // [string]   do you want text BEFORE your your tweets?
  outro_text: null,                         // [string]   do you want text AFTER your tweets?
  join_text:  null,                         // [string]   optional text in between date and tweet, try setting to "auto"
  auto_join_text_default: "we said,",        // [string]   auto text for non verb: "i said" bullocks
  auto_join_text_ed: "we",                   // [string]   auto text for past tense: "i" surfed
  auto_join_text_ing: "we am",               // [string]   auto tense for present tense: "i was" surfing
  auto_join_text_reply: "we replied to",     // [string]   auto tense for replies: "i replied to" @someone "with"
  auto_join_text_url: "we were looking at",   // [string]   auto tense for urls: "i was looking at" http:...
  loading_text: null,                       // [string]   optional loading text, displayed while tweets load
  query: null,                              // [string]   optional search query
  refresh_interval: null ,                  // [integer]  optional number of seconds after which to reload tweets
  twitter_url: "twitter.com",               // [string]   custom twitter url, if any (apigee, etc.)
  twitter_api_url: "api.twitter.com",       // [string]   custom twitter api url, if any (apigee, etc.)
  twitter_search_url: "search.twitter.com"  // [string]   custom twitter search url, if any (apigee, etc.)
};

if(o) $.extend(s, o);

$.fn.extend({
  linkUrl: function() {
    var returning = [];
    var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
    this.each(function() {
      returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>"));
    });
    return $(returning);
  },
  linkUser: function() {
    var returning = [];
    var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
    this.each(function() {
      returning.push(this.replace(regexp,"<a href=\"http://"+s.twitter_url+"/$1\">@$1</a>"));        });
    return $(returning);
  },
  linkHash: function() {
    var returning = [];
    var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi;
    this.each(function() {
      returning.push(this.replace(regexp, ' <a href="http://'+s.twitter_search_url+'/search?q=&tag=$1&lang=all&from='+s.username.join("%2BOR%2B")+'">#$1</a>'));
    });
    return $(returning);
  },
  capAwesome: function() {
    var returning = [];
    this.each(function() {
      returning.push(this.replace(/\b(awesome)\b/gi, '<span class="awesome">$1</span>'));
    });
    return $(returning);
  },
  capEpic: function() {
    var returning = [];
    this.each(function() {
      returning.push(this.replace(/\b(epic)\b/gi, '<span class="epic">$1</span>'));
    });
    return $(returning);
  },
  makeHeart: function() {
    var returning = [];
    this.each(function() {
      returning.push(this.replace(/(&lt;)+[3]/gi, "<tt class='heart'>&#x2665;</tt>"));
    });
    return $(returning);
  }
});

function parse_date(date_str) {
  // The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
  // cannot handle in IE. We therefore perform the following transformation:
  // "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000"
  return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
}

function relative_time(time_value) {
  var parsed_date = parse_date(time_value);
  var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
  var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
  var r = '';
  if (delta < 60) {
r = delta + ' seconds ago';
  } else if(delta < 120) {
r = 'a minute ago';
  } else if(delta < (45*60)) {
r = (parseInt(delta / 60, 10)).toString() + ' minutes ago';
  } else if(delta < (2*60*60)) {
r = 'an hour ago';
  } else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600, 10)).toString() + ' hours ago';
  } else if(delta < (48*60*60)) {
r = 'a day ago';
  } else {
r = (parseInt(delta / 86400, 10)).toString() + ' days ago';
  }
  return 'about ' + r;
}

function build_url() {
  var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
  if (s.list) {
    return proto+"//"+s.twitter_api_url+"/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?";
  } else if (s.query == null && s.username.length == 1) {
    return proto+'//'+s.twitter_api_url+'/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&include_rts=1&callback=?';
  } else {
    var query = (s.query || 'from:'+s.username.join(' OR from:'));
    return proto+'//'+s.twitter_search_url+'/search.json?&q='+encodeURIComponent(query)+'&rpp='+s.count+'&callback=?';
  }
}

return this.each(function(i, widget){
  var list = $('<ul class="tweet_list">').appendTo(widget);
  var intro = '<p class="tweet_intro">'+s.intro_text+'</p>';
  var outro = '<p class="tweet_outro">'+s.outro_text+'</p>';
  var loading = $('<p class="loading">'+s.loading_text+'</p>');

  if(typeof(s.username) == "string"){
    s.username = [s.username];
  }

  if (s.loading_text) $(widget).append(loading);
  $(widget).bind("load", function(){
    $.getJSON(build_url(), function(data){
      if (s.loading_text) loading.remove();
      if (s.intro_text) list.before(intro);
      list.empty();
      var tweets = (data.results || data);
      $.each(tweets, function(i,item){
        // auto join text based on verb tense and content
        if (s.join_text == "auto") {
          if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) {
            var join_text = s.auto_join_text_reply;
          } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) {
            var join_text = s.auto_join_text_url;
          } else if (item.text.match(/^((\w+ed)|just) .*/im)) {
            var join_text = s.auto_join_text_ed;
          } else if (item.text.match(/^(\w*ing) .*/i)) {
            var join_text = s.auto_join_text_ing;
          } else {
            var join_text = s.auto_join_text_default;
          }
        } else {
          var join_text = s.join_text;
        };

        var from_user = item.from_user || item.user.screen_name;
        var profile_image_url = item.profile_image_url || item.user.profile_image_url;
        var join_template = '<span class="tweet_join"> '+join_text+' </span>';
        var join = ((s.join_text) ? join_template : ' ');
        var avatar_template = '<a class="tweet_avatar" href="http://'+s.twitter_url+'/'+from_user+'"><img src="'+profile_image_url+'" height="'+s.avatar_size+'" width="'+s.avatar_size+'" alt="'+from_user+'\'s avatar" title="'+from_user+'\'s avatar" border="0"/></a>';
        var avatar = (s.avatar_size ? avatar_template : '');
        var date = ' <span class="tweet_time"><a href="http://'+s.twitter_url+'/'+from_user+'/statuses/'+item.id_str+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a></span>';
        var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>';

        // until we create a template option, arrange the items below to alter a tweet's display.
        list.append('<li>' + avatar + join + text + date + '</li>');

        list.children('li:first').addClass('tweet_first');
        list.children('li:odd').addClass('tweet_even');
        list.children('li:even').addClass('tweet_odd');
      });
      if (s.outro_text) list.after(outro);
      $(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full"));
      if (s.refresh_interval) {
        window.setTimeout(function() { $(widget).trigger("load"); }, 1000 * s.refresh_interval);
      };
    });
  }).trigger("load");
});
};
})(jQuery);


(function($){
/* hoverIntent by Brian Cherne */
$.fn.hoverIntent = function(f,g) {
	// default configuration options
	var cfg = {
		sensitivity: 7,
		interval: 100,
		timeout: 0
	};
	// override configuration options with user supplied object
	cfg = $.extend(cfg, g ? { over: f, out: g } : f );

	// instantiate variables
	// cX, cY = current X and Y position of mouse, updated by mousemove event
	// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
	var cX, cY, pX, pY;

	// A private function for getting mouse position
	var track = function(ev) {
		cX = ev.pageX;
		cY = ev.pageY;
	};

	// A private function for comparing current and previous mouse position
	var compare = function(ev,ob) {
		ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
		// compare mouse positions to see if they've crossed the threshold
		if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
			$(ob).unbind("mousemove",track);
			// set hoverIntent state to true (so mouseOut can be called)
			ob.hoverIntent_s = 1;
			return cfg.over.apply(ob,[ev]);
		} else {
			// set previous coordinates for next time
			pX = cX; pY = cY;
			// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
			ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
		}
	};

	// A private function for delaying the mouseOut function
	var delay = function(ev,ob) {
		ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
		ob.hoverIntent_s = 0;
		return cfg.out.apply(ob,[ev]);
	};

	// A private function for handling mouse 'hovering'
	var handleHover = function(e) {
		// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
		var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
		while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
		if ( p == this ) { return false; }

		// copy objects to be passed into t (required for event object to be passed in IE)
		var ev = jQuery.extend({},e);
		var ob = this;

		// cancel hoverIntent timer if it exists
		if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

		// else e.type == "onmouseover"
		if (e.type == "mouseover") {
			// set "previous" X and Y position based on initial entry point
			pX = ev.pageX; pY = ev.pageY;
			// update "current" X and Y position based on mousemove
			$(ob).bind("mousemove",track);
			// start polling interval (self-calling timeout) to compare mouse coordinates over time
			if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

		// else e.type == "onmouseout"
		} else {
			// unbind expensive mousemove event
			$(ob).unbind("mousemove",track);
			// if hoverIntent state is true, then call the mouseOut function after the specified delay
			if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
		}
	};

	// bind the function to the two event listeners
	return this.mouseover(handleHover).mouseout(handleHover);
};

})(jQuery);

$.fn.superfish = function(op){

	var sf = $.fn.superfish,
		c = sf.c,
		$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
		over = function(){
			var $$ = $(this), menu = getMenu($$);
			clearTimeout(menu.sfTimer);
			$$.showSuperfishUl().siblings().hideSuperfishUl();
		},
		out = function(){
			var $$ = $(this), menu = getMenu($$), o = sf.op;
			clearTimeout(menu.sfTimer);
			menu.sfTimer=setTimeout(function(){
				o.retainPath=($.inArray($$[0],o.$path)>-1);
				$$.hideSuperfishUl();
				if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
			},o.delay);	
		},
		getMenu = function($menu){
			var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
			sf.op = sf.o[menu.serial];
			return menu;
		},
		addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
		
	return this.each(function() {
		var s = this.serial = sf.o.length;
		var o = $.extend({},sf.defaults,op);
		o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
			$(this).addClass([o.hoverClass,c.bcClass].join(' '))
				.filter('li:has(ul)').removeClass(o.pathClass);
		});
		sf.o[s] = sf.op = o;
		
		$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
			if (o.autoArrows) addArrow( $('>a:first-child',this) );
		})
		.not('.'+c.bcClass)
			.hideSuperfishUl();
		
		var $a = $('a',this);
		$a.each(function(i){
			var $li = $a.eq(i).parents('li');
			$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
		});
		o.onInit.call(this);
		
	}).each(function() {
		var menuClasses = [c.menuClass];
		if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
		$(this).addClass(menuClasses.join(' '));
	});
};

var sf = $.fn.superfish;
sf.o = [];
sf.op = {};
sf.IE7fix = function(){
	var o = sf.op;
	if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
		this.toggleClass(sf.c.shadowClass+'-off');
	};
sf.c = {
	bcClass     : 'sf-breadcrumb',
	menuClass   : 'sf-js-enabled',
	anchorClass : 'sf-with-ul',
	arrowClass  : 'sf-sub-indicator',
	shadowClass : 'sf-shadow'
};
sf.defaults = {
	hoverClass	: 'sfHover',
	pathClass	: 'overideThisToUse',
	pathLevels	: 1,
	delay		: 800,
	animation	: {opacity:'show'},
	speed		: 'normal',
	autoArrows	: true,
	dropShadows : true,
	disableHI	: false,		// true disables hoverIntent detection
	onInit		: function(){}, // callback functions
	onBeforeShow: function(){},
	onShow		: function(){},
	onHide		: function(){}
};
$.fn.extend({
	hideSuperfishUl : function(){
		var o = sf.op,
			not = (o.retainPath===true) ? o.$path : '';
		o.retainPath = false;
		var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
				.find('>ul').hide().css('visibility','hidden');
		o.onHide.call($ul);
		return this;
	},
	showSuperfishUl : function(){
		var o = sf.op,
			sh = sf.c.shadowClass+'-off',
			$ul = this.addClass(o.hoverClass)
				.find('>ul:hidden').css('visibility','visible');
		sf.IE7fix.call($ul);
		o.onBeforeShow.call($ul);
		$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
		return this;
	}
});



(function(jQuery) {
jQuery.fn.easyAccordion = function(options) {

var defaults = {			
	slideNum: true,
	autoStart: false,
	slideInterval: 3000
};
		
this.each(function() {
	
	var settings = jQuery.extend(defaults, options);		
	jQuery(this).find('dl').addClass('easy-accordion');
	
	
	// -------- Set the variables ------------------------------------------------------------------------------
	
	jQuery.fn.setVariables = function() {
		dlWidth = jQuery(this).width();
		dlHeight = jQuery(this).height();
		dtWidth = jQuery(this).find('dt').outerHeight();
		if (jQuery.browser.msie){ dtWidth = $(this).find('dt').outerWidth();}
		dtHeight = dlHeight - (jQuery(this).find('dt').outerWidth()-jQuery(this).find('dt').width());
		slideTotal = jQuery(this).find('dt').size();
		ddWidth = dlWidth - (dtWidth*slideTotal) - (jQuery(this).find('dd').outerWidth(true)-jQuery(this).find('dd').width());
		ddHeight = dlHeight - (jQuery(this).find('dd').outerHeight(true)-jQuery(this).find('dd').height());
	};
	jQuery(this).setVariables();

	
	// -------- Fix some weird cross-browser issues due to the CSS rotation -------------------------------------

	if (jQuery.browser.safari){ var dtTop = (dlHeight-dtWidth)/2; var dtOffset = -dtTop;  /* Safari and Chrome */ }
	if (jQuery.browser.mozilla){ var dtTop = dlHeight - 20; var dtOffset = - 20; /* FF */ }
	if (jQuery.browser.msie){ var dtTop = 0; var dtOffset = 0; /* IE */ }
	
	
	// -------- Getting things ready ------------------------------------------------------------------------------
	
	var f = 1;
	jQuery(this).find('dt').each(function(){
		jQuery(this).css({'width':dtHeight,'top':dtTop,'margin-left':dtOffset});	
		if(settings.slideNum == true){
			jQuery('<span class="slide-number">'+0+f+'</span>').appendTo(this);
			if(jQuery.browser.msie){	
				var slideNumLeft = parseInt(jQuery(this).find('.slide-number').css('left')) - 14;
				jQuery(this).find('.slide-number').css({'left': slideNumLeft})
				if(jQuery.browser.version == 6.0 || jQuery.browser.version == 7.0){
					jQuery(this).find('.slide-number').css({'bottom':'auto'});
				}
				if(jQuery.browser.version == 8.0){
				var slideNumTop = jQuery(this).find('.slide-number').css('bottom');
				var slideNumTopVal = parseInt(slideNumTop) + parseInt(jQuery(this).css('padding-top'))  - 12; 
				jQuery(this).find('.slide-number').css({'bottom': slideNumTopVal}); 
				}
			} else {
				var slideNumTop = jQuery(this).find('.slide-number').css('bottom');
				var slideNumTopVal = parseInt(slideNumTop) + parseInt(jQuery(this).css('padding-top')); 
				jQuery(this).find('.slide-number').css({'bottom': slideNumTopVal}); 
			}
		}
		f = f + 1;
	});
	
	if(jQuery(this).find('.active').size()) { 
		jQuery(this).find('.active').next('dd').addClass('active');
	} else {
		jQuery(this).find('dt:first').addClass('active').next('dd').addClass('active');
	}
	
	jQuery(this).find('dt:first').css({'left':'0'}).next().css({'left':dtWidth});
	jQuery(this).find('dd').css({'width':ddWidth,'height':ddHeight});	

	
	// -------- Functions ------------------------------------------------------------------------------
	
	jQuery.fn.findActiveSlide = function() {
			var i = 1;
			this.find('dt').each(function(){
			if(jQuery(this).hasClass('active')){
				activeID = i; // Active slide
			} else if (jQuery(this).hasClass('no-more-active')){
				noMoreActiveID = i; // No more active slide
			}
			i = i + 1;
		});
	};
		
	jQuery.fn.calculateSlidePos = function() {
		var u = 2;
		jQuery(this).find('dt').not(':first').each(function(){	
			var activeDtPos = dtWidth*activeID;
			if(u <= activeID){
				var leftDtPos = dtWidth*(u-1);
				jQuery(this).animate({'left': leftDtPos});
				if(u < activeID){ // If the item sits to the left of the active element
					jQuery(this).next().css({'left':leftDtPos+dtWidth});	
				} else{ // If the item is the active one
					jQuery(this).next().animate({'left':activeDtPos});
				}
			} else {
				var rightDtPos = dlWidth-(dtWidth*(slideTotal-u+1));
				jQuery(this).animate({'left': rightDtPos});
				var rightDdPos = rightDtPos+dtWidth;
				jQuery(this).next().animate({'left':rightDdPos});	
			}
			u = u+ 1;
		});
		setTimeout( function() {
			jQuery('.easy-accordion').find('dd').not('.active').each(function(){ 
				jQuery(this).css({'display':'none'});
			});
		}, 400);
		
	};

	jQuery.fn.activateSlide = function() {
		this.parent('dl').setVariables();	
		this.parent('dl').find('dd').css({'display':'block'});
		this.parent('dl').find('dd.plus').removeClass('plus');
		this.parent('dl').find('.no-more-active').removeClass('no-more-active');
		this.parent('dl').find('.active').removeClass('active').addClass('no-more-active');
		this.addClass('active').next().addClass('active');	
		this.parent('dl').findActiveSlide();
		if(activeID < noMoreActiveID){
			this.parent('dl').find('dd.no-more-active').addClass('plus');
		}
		this.parent('dl').calculateSlidePos();	
	};

	jQuery.fn.rotateSlides = function(slideInterval, timerInstance) {
		var accordianInstance = jQuery(this);
		timerInstance.value = setTimeout(function(){accordianInstance.rotateSlides(slideInterval, timerInstance);}, slideInterval);
		jQuery(this).findActiveSlide();
		var totalSlides = jQuery(this).find('dt').size();
		var activeSlide = activeID;
		var newSlide = activeSlide + 1;
		if (newSlide > totalSlides) newSlide = 1;
		jQuery(this).find('dt:eq(' + (newSlide-1) + ')').activateSlide(); // activate the new slide
	}


	// -------- Let's do it! ------------------------------------------------------------------------------
	
	function trackerObject() {this.value = null}
	var timerInstance = new trackerObject();
	
	jQuery(this).findActiveSlide();
	jQuery(this).calculateSlidePos();
	
	if (settings.autoStart == true){
		var accordianInstance = jQuery(this);
		var interval = parseInt(settings.slideInterval);
		timerInstance.value = setTimeout(function(){
			accordianInstance.rotateSlides(interval, timerInstance);
			}, interval);
	} 

	jQuery(this).find('dt').not('active').click(function(){		
		jQuery(this).activateSlide();
		clearTimeout(timerInstance.value);
	});	
			
	if (!(jQuery.browser.msie && jQuery.browser.version == 6.0)){ 
		jQuery('dt').hover(function(){
			jQuery(this).addClass('hover');
		}, function(){
			jQuery(this).removeClass('hover');
		});
	}
});
};
})(jQuery);
