(function(F,C){var D=function(H){var G,I=[];for(G in H){if(/string|number/.test(typeof H[G])&&H[G]!==""){I.push(G+'="'+H[G]+'"')}}return I[A]("")},E=function(I){var G,K,J=[],H;if(typeof I=="object"){for(G in I){if(typeof I[G]=="object"){H=[];for(K in I[G]){H.push([K,"=",encodeURIComponent(I[G][K])][A](""))}I[G]=H[A]("&amp;")}if(I[G]){J.push(['<param name="',G,'" value="',I[G],'" />'][A](""))}}I=J[A]("")}return I},B=false,A="join";F[C]=(function(){try{var G="0,0,0",H=navigator.plugins["Shockwave Flash"]||ActiveXObject;G=H.description||(function(){try{return(new H("ShockwaveFlash.ShockwaveFlash")).GetVariable("$version")}catch(J){}}())}catch(I){}G=G.match(/^[A-Za-z\s]*?(\d+)[\.|,](\d+)(?:\s+[d|r]|,)(\d+)/);return{available:G[1]>0,activeX:H&&!H.name,version:{major:G[1]*1,minor:G[2]*1,release:G[3]*1},hasVersion:function(K){var N=this.version,L="major",M="minor",J="release";K=(/string|number/.test(typeof K))?K.toString().split("."):K||[0,0,0];K=[K[L]||K[0]||N[L],K[M]||K[1]||N[M],K[J]||K[2]||N[J]];return(K[0]<N[L])||(K[0]==N[L]&&K[1]<N[M])||(K[0]==N[L]&&K[1]==N[M]&&K[2]<=N[J])},expressInstall:"expressInstall.swf",create:function(J){if(!F[C].available||B||!typeof J=="object"||!J.swf){return false}if(J.hasVersion&&!F[C].hasVersion(J.hasVersion)){J={swf:J.expressInstall||F[C].expressInstall,attrs:{id:J.id||"SWFObjectExprInst",name:J.name,height:Math.max(J.height||137),width:Math.max(J.width||214)},params:{flashvars:{MMredirectURL:location.href,MMplayerType:(F[C].activeX)?"ActiveX":"PlugIn",MMdoctitle:document.title.slice(0,47)+" - Flash Player Installation"}}};B=true}else{J=F.extend(true,{attrs:{id:J.id,name:J.name,height:J.height||180,width:J.width||320},params:{wmode:J.wmode||"opaque",flashvars:J.flashvars}},J)}if(F[C].activeX){J.attrs.classid=J.attrs.classid||"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";J.params.movie=J.params.movie||J.swf}else{J.attrs.type=J.attrs.classid||"application/x-shockwave-flash";J.attrs.data=J.attrs.data||J.swf}return["<object ",D(J.attrs),">",E(J.params),"</object>"][A]("")}}}());F.fn[C]=function(G){if(typeof G=="object"){this.each(function(){var I=document.createElement(C);var H=F[C].create(G);if(H){I.innerHTML=H;if(I.childNodes[0]){this.appendChild(I.childNodes[0])}}})}else{if(typeof G=="function"){this.find("object").andSelf().filter("object").each(function(){var I=this,H="jsInteractionTimeoutMs";I[H]=I[H]||0;if(I[H]<660){if(I.clientWidth||I.clientHeight){G.call(this)}else{setTimeout(function(){F(I)[C](G)},I[H]+66)}}})}}return this}}(jQuery,"flash"));
/*
 * jQuery Media Plugin for converting elements into rich media content.
 *
 * Examples and documentation at: http://malsup.com/jquery/media/
 * Copyright (c) 2007-2008 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * @author: M. Alsup
 * @version: 0.92 (24-SEP-2009)
 * @requires jQuery v1.1.2 or later
 * $Id: jquery.media.js 2460 2007-07-23 02:53:15Z malsup $
 *
 * Supported Media Players:
 *	- Flash
 *	- Quicktime
 *	- Real Player
 *	- Silverlight
 *	- Windows Media Player
 *	- iframe
 *
 * Supported Media Formats:
 *	 Any types supported by the above players, such as:
 *	 Video: asf, avi, flv, mov, mpg, mpeg, mp4, qt, smil, swf, wmv, 3g2, 3gp
 *	 Audio: aif, aac, au, gsm, mid, midi, mov, mp3, m4a, snd, rm, wav, wma
 *	 Other: bmp, html, pdf, psd, qif, qtif, qti, tif, tiff, xaml
 *
 * Thanks to Mark Hicken and Brent Pedersen for helping me debug this on the Mac!
 * Thanks to Dan Rossi for numerous bug reports and code bits!
 * Thanks to Skye Giordano for several great suggestions!
 * Thanks to Richard Connamacher for excellent improvements to the non-IE behavior!
 */
;(function($) {

/**
 * Chainable method for converting elements into rich media.
 *
 * @param options
 * @param callback fn invoked for each matched element before conversion
 * @param callback fn invoked for each matched element after conversion
 */
$.fn.media = function(options, f1, f2) {
	if (options == 'undo') {
		return this.each(function() {
			var $this = $(this);
			var html = $this.data('media.origHTML');
			if (html)
				$this.replaceWith(html);
		});
	}
	
	return this.each(function() {
		if (typeof options == 'function') {
			f2 = f1;
			f1 = options;
			options = {};
		}
		var o = getSettings(this, options);
		// pre-conversion callback, passes original element and fully populated options
		if (typeof f1 == 'function') f1(this, o);

		var r = getTypesRegExp();
		var m = r.exec(o.src.toLowerCase()) || [''];

		o.type ? m[0] = o.type : m.shift();
		for (var i=0; i < m.length; i++) {
			fn = m[i].toLowerCase();
			if (isDigit(fn[0])) fn = 'fn' + fn; // fns can't begin with numbers
			if (!$.fn.media[fn])
				continue;  // unrecognized media type
			// normalize autoplay settings
			var player = $.fn.media[fn+'_player'];
			if (!o.params) o.params = {};
			if (player) {
				var num = player.autoplayAttr == 'autostart';
				o.params[player.autoplayAttr || 'autoplay'] = num ? (o.autoplay ? 1 : 0) : o.autoplay ? true : false;
			}
			var $div = $.fn.media[fn](this, o);

			$div.css('backgroundColor', o.bgColor).width(o.width);
			
			if (o.canUndo) {
				var $temp = $('<div></div>').append(this);
				$div.data('media.origHTML', $temp.html()); // store original markup
			}
			
			// post-conversion callback, passes original element, new div element and fully populated options
			if (typeof f2 == 'function') f2(this, $div[0], o, player.name);
			break;
		}
	});
};

/**
 * Non-chainable method for adding or changing file format / player mapping
 * @name mapFormat
 * @param String format File format extension (ie: mov, wav, mp3)
 * @param String player Player name to use for the format (one of: flash, quicktime, realplayer, winmedia, silverlight or iframe
 */
$.fn.media.mapFormat = function(format, player) {
	if (!format || !player || !$.fn.media.defaults.players[player]) return; // invalid
	format = format.toLowerCase();
	if (isDigit(format[0])) format = 'fn' + format;
	$.fn.media[format] = $.fn.media[player];
	$.fn.media[format+'_player'] = $.fn.media.defaults.players[player];
};

// global defautls; override as needed
$.fn.media.defaults = {
	standards:  false,      // use object tags only (no embeds for non-IE browsers)
	canUndo:    true,       // tells plugin to store the original markup so it can be reverted via: $(sel).mediaUndo()
	width:		400,
	height:		400,
	autoplay:	0,		   	// normalized cross-player setting
	bgColor:	'#ffffff', 	// background color
	params:		{ wmode: 'transparent'},	// added to object element as param elements; added to embed element as attrs
	attrs:		{},			// added to object and embed elements as attrs
	flvKeyName: 'file', 	// key used for object src param (thanks to Andrea Ercolino)
	flashvars:	{},			// added to flash content as flashvars param/attr
	flashVersion:	'7',	// required flash version
	expressInstaller: null,	// src for express installer

	// default flash video and mp3 player (@see: http://jeroenwijering.com/?item=Flash_Media_Player)
	flvPlayer:	 'mediaplayer.swf',
	mp3Player:	 'mediaplayer.swf',

	// @see http://msdn2.microsoft.com/en-us/library/bb412401.aspx
	silverlight: {
		inplaceInstallPrompt: 'true', // display in-place install prompt?
		isWindowless:		  'true', // windowless mode (false for wrapping markup)
		framerate:			  '24',	  // maximum framerate
		version:			  '0.9',  // Silverlight version
		onError:			  null,	  // onError callback
		onLoad:			      null,   // onLoad callback
		initParams:			  null,	  // object init params
		userContext:		  null	  // callback arg passed to the load callback
	}
};

// Media Players; think twice before overriding
$.fn.media.defaults.players = {
	flash: {
		name:		 'flash',
		title:		 'Flash',
		types:		 'flv,mp3,swf',
		mimetype:	 'application/x-shockwave-flash',
		pluginspage: 'http://www.adobe.com/go/getflashplayer',
		ieAttrs: {
			classid:  'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
			type:	  'application/x-oleobject',
			codebase: 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + $.fn.media.defaults.flashVersion
		}
	},
	quicktime: {
		name:		 'quicktime',
		title:		 'QuickTime',
		mimetype:	 'video/quicktime',
		pluginspage: 'http://www.apple.com/quicktime/download/',
		types:		 'aif,aiff,aac,au,bmp,gsm,mov,mid,midi,mpg,mpeg,mp4,m4a,psd,qt,qtif,qif,qti,snd,tif,tiff,wav,3g2,3gp',
		ieAttrs: {
			classid:  'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
			codebase: 'http://www.apple.com/qtactivex/qtplugin.cab'
		}
	},
	realplayer: {
		name:		  'real',
		title:		  'RealPlayer',
		types:		  'ra,ram,rm,rpm,rv,smi,smil',
		mimetype:	  'audio/x-pn-realaudio-plugin',
		pluginspage:  'http://www.real.com/player/',
		autoplayAttr: 'autostart',
		ieAttrs: {
			classid: 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA'
		}
	},
	winmedia: {
		name:		  'winmedia',
		title:		  'Windows Media',
		types:		  'asx,asf,avi,wma,wmv',
		mimetype:	  $.browser.mozilla && isFirefoxWMPPluginInstalled() ? 'application/x-ms-wmp' : 'application/x-mplayer2',
		pluginspage:  'http://www.microsoft.com/Windows/MediaPlayer/',
		autoplayAttr: 'autostart',
		oUrl:		  'url',
		ieAttrs: {
			classid:  'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6',
			type:	  'application/x-oleobject'
		}
	},
	// special cases
	iframe: {
		name:  'iframe',
		types: 'html,pdf'
	},
	silverlight: {
		name:  'silverlight',
		types: 'xaml'
	}
};

//
//	everything below here is private
//


// detection script for FF WMP plugin (http://www.therossman.org/experiments/wmp_play.html)
// (hat tip to Mark Ross for this script)
function isFirefoxWMPPluginInstalled() {
	var plugs = navigator.plugins;
	for (i = 0; i < plugs.length; i++) {
		var plugin = plugs[i];
		if (plugin['filename'] == 'np-mswmp.dll')
			return true;
	}
	return false;
}

var counter = 1;

for (var player in $.fn.media.defaults.players) {
	var types = $.fn.media.defaults.players[player].types;
	$.each(types.split(','), function(i,o) {
		if (isDigit(o[0])) o = 'fn' + o;
		$.fn.media[o] = $.fn.media[player] = getGenerator(player);
		$.fn.media[o+'_player'] = $.fn.media.defaults.players[player];
	});
};

function getTypesRegExp() {
	var types = '';
	for (var player in $.fn.media.defaults.players) {
		if (types.length) types += ',';
		types += $.fn.media.defaults.players[player].types;
	};
	return new RegExp('\\.(' + types.replace(/,/ig,'|') + ')\\b');
};

function getGenerator(player) {
	return function(el, options) {
		return generate(el, options, player);
	};
};

function isDigit(c) {
	return '0123456789'.indexOf(c) > -1;
};

// flatten all possible options: global defaults, meta, option obj
function getSettings(el, options) {
	options = options || {};
	var $el = $(el);
	var cls = el.className || '';
	// support metadata plugin (v1.0 and v2.0)
	var meta = $.metadata ? $el.metadata() : $.meta ? $el.data() : {};
	meta = meta || {};
	var w = meta.width	 || parseInt(((cls.match(/w:(\d+)/)||[])[1]||0));
	var h = meta.height || parseInt(((cls.match(/h:(\d+)/)||[])[1]||0));

	if (w) meta.width	= w;
	if (h) meta.height = h;
	if (cls) meta.cls = cls;

	var a = $.fn.media.defaults;
	var b = options;
	var c = meta;

	var p = { params: { bgColor: options.bgColor || $.fn.media.defaults.bgColor } };
	var opts = $.extend({}, a, b, c);
	$.each(['attrs','params','flashvars','silverlight'], function(i,o) {
		opts[o] = $.extend({}, p[o] || {}, a[o] || {}, b[o] || {}, c[o] || {});
	});

	if (typeof opts.caption == 'undefined') opts.caption = $el.text();

	// make sure we have a source!
	opts.src = opts.src || $el.attr('href') || $el.attr('src') || 'unknown';
	return opts;
};

//
//	Flash Player
//

// generate flash using SWFObject library if possible
$.fn.media.swf = function(el, opts) {
	if (!window.SWFObject && !window.swfobject) {
		// roll our own
		if (opts.flashvars) {
			var a = [];
			for (var f in opts.flashvars)
				a.push(f + '=' + opts.flashvars[f]);
			if (!opts.params) opts.params = {};
			opts.params.flashvars = a.join('&');
		}
		return generate(el, opts, 'flash');
	}

	var id = el.id ? (' id="'+el.id+'"') : '';
	var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	var $div = $('<div' + id + cls + '>');

	// swfobject v2+
	if (window.swfobject) {
		$(el).after($div).appendTo($div);
		if (!el.id) el.id = 'movie_player_' + counter++;

		// replace el with swfobject content
		swfobject.embedSWF(opts.src, el.id, opts.width, opts.height, opts.flashVersion,
			opts.expressInstaller, opts.flashvars, opts.params, opts.attrs);
	}
	// swfobject < v2
	else {
		$(el).after($div).remove();
		var so = new SWFObject(opts.src, 'movie_player_' + counter++, opts.width, opts.height, opts.flashVersion, opts.bgColor);
		if (opts.expressInstaller) so.useExpressInstall(opts.expressInstaller);

		for (var p in opts.params)
			if (p != 'bgColor') so.addParam(p, opts.params[p]);
		for (var f in opts.flashvars)
			so.addVariable(f, opts.flashvars[f]);
		so.write($div[0]);
	}

	if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	return $div;
};

// map flv and mp3 files to the swf player by default
$.fn.media.flv = $.fn.media.mp3 = function(el, opts) {
	var src = opts.src;
	var player = /\.mp3\b/i.test(src) ? $.fn.media.defaults.mp3Player : $.fn.media.defaults.flvPlayer;
	var key = opts.flvKeyName;
	src = encodeURIComponent(src);
	opts.src = player;
	opts.src = opts.src + '?'+key+'=' + (src);
	var srcObj = {};
	srcObj[key] = src;
	opts.flashvars = $.extend({}, srcObj, opts.flashvars );
	return $.fn.media.swf(el, opts);
};

//
//	Silverlight
//
$.fn.media.xaml = function(el, opts) {
	if (!window.Sys || !window.Sys.Silverlight) {
		if ($.fn.media.xaml.warning) return;
		$.fn.media.xaml.warning = 1;
		alert('You must include the Silverlight.js script.');
		return;
	}

	var props = {
		width: opts.width,
		height: opts.height,
		background: opts.bgColor,
		inplaceInstallPrompt: opts.silverlight.inplaceInstallPrompt,
		isWindowless: opts.silverlight.isWindowless,
		framerate: opts.silverlight.framerate,
		version: opts.silverlight.version
	};
	var events = {
		onError: opts.silverlight.onError,
		onLoad: opts.silverlight.onLoad
	};

	var id1 = el.id ? (' id="'+el.id+'"') : '';
	var id2 = opts.id || 'AG' + counter++;
	// convert element to div
	var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	var $div = $('<div' + id1 + cls + '>');
	$(el).after($div).remove();

	Sys.Silverlight.createObjectEx({
		source: opts.src,
		initParams: opts.silverlight.initParams,
		userContext: opts.silverlight.userContext,
		id: id2,
		parentElement: $div[0],
		properties: props,
		events: events
	});

	if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	return $div;
};

//
// generate object/embed markup
//
function generate(el, opts, player) {
	var $el = $(el);
	var o = $.fn.media.defaults.players[player];

	if (player == 'iframe') {
		var o = $('<iframe' + ' width="' + opts.width + '" height="' + opts.height + '" >');
		o.attr('src', opts.src);
		o.css('backgroundColor', o.bgColor);
	}
	else if ($.browser.msie) {
		var a = ['<object width="' + opts.width + '" height="' + opts.height + '" '];
		for (var key in opts.attrs)
			a.push(key + '="'+opts.attrs[key]+'" ');
		for (var key in o.ieAttrs || {}) {
			var v = o.ieAttrs[key];
			if (key == 'codebase' && window.location.protocol == 'https:')
				v = v.replace('http','https');
			a.push(key + '="'+v+'" ');
		}
		a.push('></ob'+'ject'+'>');
		var p = ['<param name="' + (o.oUrl || 'src') +'" value="' + opts.src + '">'];
		for (var key in opts.params)
			p.push('<param name="'+ key +'" value="' + opts.params[key] + '">');
		var o = document.createElement(a.join(''));
		for (var i=0; i < p.length; i++)
			o.appendChild(document.createElement(p[i]));
	}
	else if (o.standards) {
		// Rewritten to be standards compliant by Richard Connamacher
		var a = ['<object type="' + o.mimetype +'" width="' + opts.width + '" height="' + opts.height +'"'];
		if (opts.src) a.push(' data="' + opts.src + '" ');
		a.push('>');
		a.push('<param name="' + (o.oUrl || 'src') +'" value="' + opts.src + '">');
		for (var key in opts.params) {
			if (key == 'wmode' && player != 'flash') // FF3/Quicktime borks on wmode
				continue;
			a.push('<param name="'+ key +'" value="' + opts.params[key] + '">');
		}
		// Alternate HTML
		a.push('<div><p><strong>'+o.title+' Required</strong></p><p>'+o.title+' is required to view this media. <a href="'+o.pluginspage+'">Download Here</a>.</p></div>');
		a.push('</ob'+'ject'+'>');
	}
	 else {
	        var a = ['<embed width="' + opts.width + '" height="' + opts.height + '" style="display:block"'];
	        if (opts.src) a.push(' src="' + opts.src + '" ');
	        for (var key in opts.attrs)
	            a.push(key + '="'+opts.attrs[key]+'" ');
	        for (var key in o.eAttrs || {})
	            a.push(key + '="'+o.eAttrs[key]+'" ');
	        for (var key in opts.params) {
	            if (key == 'wmode' && player != 'flash') // FF3/Quicktime borks on wmode
	            	continue;
	            a.push(key + '="'+opts.params[key]+'" ');
	        }
	        a.push('></em'+'bed'+'>');
	    }	
	// convert element to div
	var id = el.id ? (' id="'+el.id+'"') : '';
	var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
	var $div = $('<div' + id + cls + '>');
	$el.after($div).remove();
	($.browser.msie || player == 'iframe') ? $div.append(o) : $div.html(a.join(''));
	if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
	return $div;
};


})(jQuery);

/*
* jTweetsAnywhere V1.2.0
* http://thomasbillenstein.com/jTweetsAnywhere/
*
* Copyright 2010, Thomas Billenstein
* Licensed under the MIT license.
* http://thomasbillenstein.com/jTweetsAnywhere/license.txt
*/
(function ($) {
    $.fn.jTweetsAnywhere = function (options) {
        // setup the default options
        var options = $.extend(
		{
		    /**
		    * The user's name who's tweet feed or list feed is displayed. This
		    * param is also used when a Twitter "Follow Button" is displayed. Usually
		    * this param is a string, but can also be an array of strings. If an array
		    * is supplied (and the params 'list' and 'searchParams' are null), a
		    * combined feed of all users is displayed.
		    *
		    * Sample: 'tbillenstein' or ['twitterapi', '...', '...']
		    */
		    username: 'tbillenstein',

		    /**
		    * The name of a user's list where the tweet feed is generated from
		    */
		    list: null,

		    /**
		    * A single search param string or an array of search params, to be used in
		    * a Twitter search call. All Twitter Search Params are supported
		    * See here for the details:
		    * http://apiwiki.twitter.com/Twitter-Search-API-Method%3A-search
		    *
		    * Sample: 'q=twitter' or ['q=twitter', 'geocode=48.856667,2.350833,30km']
		    */
		    searchParams: null,

		    /**
		    * The number of tweets shown in the tweet feed. If this param is 0, no feed
		    * is displayed. For user or list feeds the maximum count is 20, for search
		    * results the maximum count is 100.
		    *
		    * Unlike in previous releases, since 1.2.0 jTweetsAnywhere is based on a
		    * tweets caching algorithm that will always deliver the requested count of
		    * tweets accepting that this request can only be fullfilled by calling Twitter
		    * more than once.
		    *
		    * IMPORTANT: Please always keep in mind, that the use of the Twitter API is
		    * rate limited. Non-authenticated users are rated IP-based and you have only
		    * 150 calls per hour available. Every retrieval of tweets counts and so does
		    * for example hovering over a profile image to show the hovercard. The rate
		    * limit is not limited to a special application or plugin like jTweetsAnywhere
		    * but counts for all of them running on the same machine/ip. jTweetsAnywhere
		    * will always check the remaining count of free API calls before actually
		    * calling Twitter to avoid black listing your visitor's IP.
		    */
		    count: 0,

		    /**
		    * A flag (true/false) that specifies whether to display a profile image in
		    * tweets. If the param is set to null (the default value), a profile image
		    * is displayed only if the feed represents a user's list or the result of a
		    * Twitter search.
		    *
		    * THIS OPTION IS DEPRECATED. You should use showTweetFeed.showProfileImages
		    * instead.
		    */
		    tweetProfileImagePresent: null,

		    /**
		    * Each tweet that is loaded from Twitter will pass the tweetFilter. if
		    * the filter returns true, the tweet will be added to the tweets cache
		    * otherwise it is ignored. The defaultTweetFilter alsways retruns true
		    * but you can supply your own tweet filter to customize the tweet feed.
		    */
		    tweetFilter: defaultTweetFilter,

		    /**
		    * A flag (true/false) that specifies whether to display a Tweet Feed
		    * or an object literal representing the configuration options for the
		    * Tweet Feed. This flag works in conjunction with the count parameter:
		    * - if count equals 0, no feed is displayed, ignoring showTweetFeed
		    * - if count not equals 0 and showTweetFeed equals false, no feed
		    *   is displayed
		    * {
		    *     expandHovercards: false,		// Boolean - Show Hovercards in expanded mode.
		    *
		    *     showTimestamp: true, 		// A flag (true/false) that specifies whether to display a tweet's timestamp
		    * 									// or an object literal representing the configuration options for the
		    * 									// timestamp.
		    * 									// {
		    * 									//     refreshInterval: 0,	// Time in seconds to be waited until the
		    * 									//							// timestamps of the displayed tweets get refreshed
		    *									// 							// 0 means no refreshing.
		    * 									// }
		    *
		    *     showSource: false,			// Boolean - Show info about the source of the tweet.
		    *
		    *     showGeoLocation: true,		// Boolean - Show geolocation info and link to Google maps.
		    *
		    *     showInReplyTo: true,			// Boolean - Show link to the "replied to" tweet (if available).
		    *
		    *     showProfileImages: null,		// A flag (true/false) that specifies whether to display a profile image in
		    * 									// tweets. If the param is set to null (the default value), a profile image
		    * 									// is displayed only if the feed represents a user's list or the result of a
		    * 									// Twitter search.
		    *
		    *     showUserScreenNames: null,	// A flag (true/false/null) that specifies whether to display a username in
		    * 									// tweets. If the param is set to null (the default value), a username
		    * 									// is displayed only if the feed represents a user's list or the result of a
		    * 									// Twitter search.
		    *
		    *     showUserFullNames: false,	// A flag (true/false/null) that specifies whether to display a user's full name
		    * 									// in tweets. If the param is set to null, a user's full name
		    * 									// is displayed only if the feed represents a user's list or the result of a
		    * 									// Twitter search.
		    *
		    *	   includeRetweets: true,		// Boolean - Include native retweets in a user's tweet feed
		    *
		    *     paging:						// An object literal representing the configuration options for the
		    *     {							// paging support, that specifies how more/earlier tweets can be loaded
		    *         mode: "none"		   		// by using the supplied UI controls (more/next buttons, scrollbar).
		    *     },                           // Accepted values for mode are: "none" | "more" | "prev-next" | "endless-scroll"
		    *									// if mode equals "endless-scroll" you have to set the height of the tweet feed
		    *									// element (.jta-tweet-list) in your CSS to get a scrollbar! You should also set
		    *									// the "overflow" attribute to "auto".
		    *
		    *     autorefresh:					// An object literal representing the configuration options for the
		    *	   {							// autorefresh behaviour.
		    *
		    *									// IMPORTANT: Please always keep in mind, that using the Twitter API is rate
		    *									// limited. Non-authenticated users are rated IP-based and you have only 150
		    *									// calls per hour available. Every retrieval of tweets counts and so does for
		    *									// example hovering over a profile image to show the hovercard. The rate limit
		    *									// is not limited to a special application or plugin like jTweetsAnywhere but
		    *									// counts for all of them running on the same machine/ip. jTweetsAnywhere will
		    *									// always check the remaining count of free API calls before actually calling
		    *									// Twitter to avoid black listing your visitor's IP.
		    *
		    * 									// However - choose your settings wisely to keep your visitors happy. An update
		    *									// interval of 30 seconds on a feed that is updated averaged once per hour
		    *									// does not make sense and is a total waste of remaining API calls!
		    *
		    *	       mode: "none",            // Accepted values for mode are: "none" | "auto-insert" | "trigger-insert"
		    *									// "none" (the default value) - disables the autorefresh feature
		    *									// "auto-insert" - automatically insert the new tweets on top of the tweet feed
		    *									// "trigger-insert" - if new tweets arrived, show or update a button that displays
		    *									// the number of new tweets. These new tweets are inserted on top of the tweet
		    *									// feed, if the user clicks on the button.
		    *
		    *	       interval: 60,			// Time in seconds to be waited until the next request for new tweets. Minimum
		    *									// value is 30.
		    *
		    *         duration: 3600			// Time in seconds for how long the autorefresh will be active. After
		    *									// this period of time, autorefreshing will stop. A value of -1 means
		    *									// autorefresh for ever.
		    *    }
		    * }
		    */
		    showTweetFeed: true,

		    /**
		    * A flag (true/false) that specifies whether to display a Twitter "Follow
		    * Button".
		    */
		    showFollowButton: false,

		    /**
		    * A flag (true/false) that specifies whether to display a Twitter "Connect
		    * Button" or an object literal representing the configuration options for
		    * the "Tweet Box".
		    * {
		    *     size: 'medium'				// String - The size of the Connect Button. Valid values are: small, medium, large, xlarge
		    * }
		    */
		    showConnectButton: false,

		    /**
		    * A flag (true/false) that specifies whether to display Login Infos.
		    */
		    showLoginInfo: false,

		    /**
		    * A flag (true/false) that specifies whether to display a Twitter "Tweet
		    * Box" or an object literal representing the configuration options for
		    * the "Tweet Box".
		    * {
		    *     counter: true,				// Boolean - Display a counter in the Tweet Box for counting characters
		    *     width: 515,					// Number - The width of the Tweet Box in pixels
		    *     height: 65,					// Number - The height of the Tweet Box in pixels
		    *     label: "What's happening",	// String - The text above the Tweet Box, a call to action
		    *     defaultContent: <none>,		// String - Pre-populated text in the Tweet Box. Useful for an @mention, a #hashtag, a link, etc.
		    *     onTweet: <none>				// Function - Specify a listener for when a tweet is sent from the Tweet Box. The listener receives two arguments: a plaintext tweet and an HTML tweet
		    * }
		    */
		    showTweetBox: false,

		    /**
		    * A decorator is a function that is responsible for constructing a certain
		    * element of the widget. Most of the decorators return a HTML string.
		    * Exceptions are the mainDecorator, which defines the basic sequence of
		    * the widget's components, plus the linkDecorator, the usernameDecorator
		    * and the hashtagDecorator which return the string that is supplied as a
		    * function param, enriched with the HTML tags.
		    *
		    * For details, see the implementations of the default decorators. Each
		    * default decorator can be overwritten by your own implementation.
		    */
		    mainDecorator: defaultMainDecorator,

		    tweetFeedDecorator: defaultTweetFeedDecorator,

		    tweetDecorator: defaultTweetDecorator,
		    tweetProfileImageDecorator: defaultTweetProfileImageDecorator,
		    tweetBodyDecorator: defaultTweetBodyDecorator,
		    tweetUsernameDecorator: defaultTweetUsernameDecorator,
		    tweetTextDecorator: defaultTweetTextDecorator,
		    tweetAttributesDecorator: defaultTweetAttributesDecorator,
		    tweetTimestampDecorator: defaultTweetTimestampDecorator,
		    tweetSourceDecorator: defaultTweetSourceDecorator,
		    tweetGeoLocationDecorator: defaultTweetGeoLocationDecorator,
		    tweetInReplyToDecorator: defaultTweetInReplyToDecorator,
		    tweetRetweeterDecorator: defaultTweetRetweeterDecorator,

		    tweetFeedControlsDecorator: defaultTweetFeedControlsDecorator,
		    tweetFeedControlsMoreBtnDecorator: defaultTweetFeedControlsMoreBtnDecorator,
		    tweetFeedControlsPrevBtnDecorator: defaultTweetFeedControlsPrevBtnDecorator,
		    tweetFeedControlsNextBtnDecorator: defaultTweetFeedControlsNextBtnDecorator,

		    tweetFeedAutorefreshTriggerDecorator: defaultTweetFeedAutorefreshTriggerDecorator,
		    tweetFeedAutorefreshTriggerContentDecorator: defaultTweetFeedAutorefreshTriggerContentDecorator,

		    connectButtonDecorator: defaultConnectButtonDecorator,

		    loginInfoDecorator: defaultLoginInfoDecorator,
		    loginInfoContentDecorator: defaultLoginInfoContentDecorator,

		    followButtonDecorator: defaultFollowButtonDecorator,

		    tweetBoxDecorator: defaultTweetBoxDecorator,

		    linkDecorator: defaultLinkDecorator,
		    usernameDecorator: defaultUsernameDecorator,
		    hashtagDecorator: defaultHashtagDecorator,

		    loadingDecorator: defaultLoadingDecorator,
		    errorDecorator: defaultErrorDecorator,
		    noDataDecorator: defaultNoDataDecorator,

		    /**
		    * Formatters are currently used for date format processing only.
		    *
		    * The tweetTimestampFormatter formats the tweet's timestamp to be shown
		    * in the tweet attributes section
		    *
		    * For details, see the implementation of the defaultTweetTimestampFormatter.
		    */
		    tweetTimestampFormatter: defaultTweetTimestampFormatter,

		    /**
		    * The tweetTimestampTooltipFormatter formats the tweet's timestamp to be shown
		    * in the tooltip when hovering over the timestamp link.
		    */
		    tweetTimestampTooltipFormatter: defaultTweetTimestampTooltipFormatter,

		    /**
		    * A visualizer is a function that is responsible for adding one or more
		    * elements to the DOM and thereby making them visible to the user.
		    * A visualizer might also be responsible to do the opposite effect:
		    * To remove one or more elements from the DOM.
		    *
		    * The tweetVisualizer gets called each time a tweet element should be
		    * appended or prepended to the tweet feed element.
		    *
		    * For details, see the implementation of the defaultTweetVisualizer.
		    *
		    * Each default visualizer can be overwritten by your own implementation.
		    */
		    tweetVisualizer: defaultTweetVisualizer,

		    /**
		    * The loadingIndicatorVisualizer gets called each time data is retrieved
		    * from Twitter to visualize the loading indicator. This visualizer is also
		    * used to hide the loading indicator.
		    *
		    * For details, see the implementation of the defaultLoadingIndicatorVisualizer.
		    */
		    loadingIndicatorVisualizer: defaultLoadingIndicatorVisualizer,

		    /**
		    * The autorefreshTriggerVisualizer will be called if the autorefresh
		    * trigger should be visualized or hidden.
		    *
		    * For details, see the implementation of the autorefreshTriggerVisualizer.
		    */
		    autorefreshTriggerVisualizer: defaultAutorefreshTriggerVisualizer,

		    /**
		    * An event handler is a function that gets called whenever the event you
		    * are interested in, occurs.
		    *
		    * The onDataRequest event handler will be called immediatly before calling
		    * Twitter to retrieve new data and gives you the opportunity to deny
		    * the call by returning false from the function.
		    *
		    * This feature might be used in conjunction with the paging feature,
		    * especially when using the "endless-scroll" paging mode, to avoid the
		    * exhaustion of remaining Twitter API calls, before the rate limit is
		    * reached. The stats parameter contains statistical infos and counters
		    * that you can examine to base your decision whether to return true or
		    * false.
		    */
		    onDataRequestHandler: defaultOnDataRequestHandler,

		    /**
		    * The onRateLimitData event handler is called each time
		    * jTweetsAnywhere retrieved the rate limit data from Twitter. The actual
		    * rate limit data is contained in the stats object.
		    */
		    onRateLimitDataHandler: defaultOnRateLimitDataHandler,

		    _tweetFeedConfig:
			{
			    expandHovercards: false,
			    showTimestamp:
				{
				    refreshInterval: 0
				},
			    showSource: false,
			    showGeoLocation: true,
			    showInReplyTo: true,
			    showProfileImages: null,
			    showUserScreenNames: null,
			    showUserFullNames: false,
			    includeRetweets: true,
			    paging:
				{
				    mode: "none",
				    _limit: 0,
				    _offset: 0
				},
			    autorefresh:
				{
				    mode: "none",
				    interval: 60,
				    duration: 3600,
				    _startTime: null,
				    _triggerElement: null
				},
			    _pageParam: 0,
			    _maxId: 0,
			    _recLevel: 0,
			    _noData: false,
			    _clearBeforePopulate: false
			},
		    _tweetBoxConfig:
			{
			    counter: true,
			    width: 515,
			    height: 65,
			    label: "What's happening?",
			    defaultContent: '',
			    onTweet: function (textTweet, htmlTweet) { }
			},
		    _connectButtonConfig:
			{
			    size: "medium"
			},
		    _baseSelector: null,
		    _baseElement: null,
		    _tweetFeedElement: null,
		    _tweetFeedControlsElement: null,
		    _followButtonElement: null,
		    _loginInfoElement: null,
		    _connectButtonElement: null,
		    _tweetBoxElement: null,
		    _loadingIndicatorElement: null,
		    _noDataElement: null,
		    _tweetsCache: [],
		    _autorefreshTweetsCache: [],
		    _stats:
			{
			    dataRequestCount: 0,
			    rateLimitPreventionCount: 0,
			    rateLimit:
				{
				    remaining_hits: 150,
				    hourly_limit: 150
				}
			}
		}, options);

        // no main decorator? nothing to do!
        if (!options.mainDecorator) {
            return;
        }

        options._baseSelector = this.selector;

        // if username is an array, create the search query and flatten username
        if (typeof (options.username) != 'string') {
            if (!options.searchParams) {
                options.searchParams = ['q=from:' + options.username.join(" OR from:")];
            }

            options.username = options.username[0];
        }

        // if showTweetFeed is not set to a boolean value, we expect the configuration of
        // the tweet feed
        if (typeof (options.showTweetFeed) == 'object') {
            $.extend(true, options._tweetFeedConfig, options.showTweetFeed);
        }

        // if showTweetBox is not set to a boolean value, we expect the configuration of
        // the TweetBox
        if (typeof (options.showTweetBox) == 'object') {
            options._tweetBoxConfig = options.showTweetBox;
            options.showTweetBox = true;
        }

        // if showConnectButton is not set to a boolean value, we expect the
        // configuration of the Connect Button
        if (typeof (options.showConnectButton) == 'object') {
            options._connectButtonConfig = options.showConnectButton;
            options.showConnectButton = true;
        }

        // to be compatible, check the deprecated option 'tweetProfileImagePresent'
        if (options._tweetFeedConfig.showProfileImages == null) {
            options._tweetFeedConfig.showProfileImages = options.tweetProfileImagePresent;
        }

        // if _tweetFeedConfig.showProfileImages is not set to a boolean value,
        // we decide to show a profile image if the feed represents a user's
        // list or the results of a Twitter search
        if (options._tweetFeedConfig.showProfileImages == null) {
            options._tweetFeedConfig.showProfileImages = (options.list || options.searchParams) && options.tweetProfileImageDecorator;
        }

        // if _tweetFeedConfig.showUserScreenNames is not set to a boolean value,
        // we decide to show a username if the feed represents a user's
        // list or the results of a Twitter search or a tweet is a native retweet
        if (options._tweetFeedConfig.showUserScreenNames == null) {
            if (options.list || options.searchParams) {
                options._tweetFeedConfig.showUserScreenNames = true;
            }

            if (!options.tweetUsernameDecorator) {
                options._tweetFeedConfig.showUserScreenNames = false;
            }
        }

        // if _tweetFeedConfig.showUserFullNames is not set to a boolean value,
        // we decide to show a user's full name if the feed represents a user's
        // list or the results of a Twitter search or a tweet is a native retweet
        if (options._tweetFeedConfig.showUserFullNames == null) {
            if (options.list || options.searchParams) {
                options._tweetFeedConfig.showUserFullNames = true;
            }

            if (!options.tweetUsernameDecorator) {
                options._tweetFeedConfig.showUserFullNames = false;
            }
        }

        options.count = validateRange(options.count, 0, options.searchParams ? 100 : 20);

        options._tweetFeedConfig.autorefresh.interval = Math.max(30, options._tweetFeedConfig.autorefresh.interval);

        options._tweetFeedConfig.paging._offset = 0;
        options._tweetFeedConfig.paging._limit = options.count;

        // internally, the decision of what parts of a widget are to be
        // displayed is based on the existence of the decorators
        if (options.count == 0 || !options.showTweetFeed) {
            options.tweetFeedDecorator = null;
            options.tweetFeedControlsDecorator = null;
        }

        if (options._tweetFeedConfig.paging.mode == 'none') {
            options.tweetFeedControlsDecorator = null;
        }

        if (!options.showFollowButton) {
            options.followButtonDecorator = null;
        }

        if (!options.showTweetBox) {
            options.tweetBoxDecorator = null;
        }

        if (!options.showConnectButton) {
            options.connectButtonDecorator = null;
        }

        if (!options.showLoginInfo) {
            options.loginInfoDecorator = null;
        }

        if (!options._tweetFeedConfig.showTimestamp) {
            options.tweetTimestampDecorator = null;
        }

        if (!options._tweetFeedConfig.showSource) {
            options.tweetSourceDecorator = null;
        }

        if (!options._tweetFeedConfig.showGeoLocation) {
            options.tweetGeoLocationDecorator = null;
        }

        if (!options._tweetFeedConfig.showInReplyTo) {
            options.tweetInReplyToDecorator = null;
        }

        // setup ajax
        $.ajaxSetup({ cache: true });

        return this.each(function () {
            // the DOM element, where to display the widget
            options._baseElement = $(this);

            // create the widget's necessary sub DOM elements
            options._tweetFeedElement = options.tweetFeedDecorator ? $(options.tweetFeedDecorator(options)) : null;
            options._tweetFeedControlsElement = options.tweetFeedControlsDecorator ? $(options.tweetFeedControlsDecorator(options)) : null;
            options._followButtonElement = options.followButtonDecorator ? $(options.followButtonDecorator(options)) : null;
            options._tweetBoxElement = options.tweetBoxDecorator ? $(options.tweetBoxDecorator(options)) : null;
            options._connectButtonElement = options.connectButtonDecorator ? $(options.connectButtonDecorator(options)) : null;
            options._loginInfoElement = options.loginInfoDecorator ? $(options.loginInfoDecorator(options)) : null;

            // add the widget to the DOM
            options.mainDecorator(options);

            populateTweetFeed(options);
            populateAnywhereControls(options);

            // bind event handlers to support paging
            bindEventHandlers(options);

            // install autorefresh support
            options._tweetFeedConfig.autorefresh._startTime = new Date().getTime();
            startAutorefresh(options);
            startTimestampRefresh(options);
        });
    };
    defaultMainDecorator = function (options) {
        // defines the default sequence of the widget's elements
        if (options._tweetFeedElement) {
            options._baseElement.append(options._tweetFeedElement);
        }

        if (options._tweetFeedControlsElement) {
            options._baseElement.append(options._tweetFeedControlsElement);
        }

        if (options._connectButtonElement) {
            options._baseElement.append(options._connectButtonElement);
        }

        if (options._loginInfoElement) {
            options._baseElement.append(options._loginInfoElement);
        }

        if (options._followButtonElement) {
            options._baseElement.append(options._followButtonElement);
        }

        if (options._tweetBoxElement) {
            options._baseElement.append(options._tweetBoxElement);
        }
    };
    defaultTweetFeedControlsDecorator = function (options) {
        // the default tweet feed's paging controls
        var html = '';

        if (options._tweetFeedConfig.paging.mode == 'prev-next') {
            if (options.tweetFeedControlsPrevBtnDecorator) {
                html += options.tweetFeedControlsPrevBtnDecorator(options);
            }

            if (options.tweetFeedControlsNextBtnDecorator) {
                html += options.tweetFeedControlsNextBtnDecorator(options);
            }
        }
        else if (options._tweetFeedConfig.paging.mode == 'endless-scroll') {
            // nothing to do here atm
        }
        else {
            if (options.tweetFeedControlsMoreBtnDecorator) {
                html += options.tweetFeedControlsMoreBtnDecorator(options);
            }
        }

        return '<div class="jta-tweet-list-controls">' + html + '</div>';
    };
    defaultTweetFeedControlsMoreBtnDecorator = function (options) {
        return '<span class="jta-tweet-list-controls-button jta-tweet-list-controls-button-more">' + 'More' + '</span>';
    };
    defaultTweetFeedControlsPrevBtnDecorator = function (options) {
        return '<span class="jta-tweet-list-controls-button jta-tweet-list-controls-button-prev">' + 'Prev' + '</span>';
    };
    defaultTweetFeedControlsNextBtnDecorator = function (options) {
        return '<span class="jta-tweet-list-controls-button jta-tweet-list-controls-button-next">' + 'Next' + '</span>';
    };
    defaultTweetFeedAutorefreshTriggerDecorator = function (count, options) {
        var html = '';

        if (options.tweetFeedAutorefreshTriggerContentDecorator) {
            html = options.tweetFeedAutorefreshTriggerContentDecorator(count, options);
        }

        return '<li class="jta-tweet-list-autorefresh-trigger">' + html + '</li>';
    };
    defaultTweetFeedAutorefreshTriggerContentDecorator = function (count, options) {
        var content = '' + count + ' new ' + (count > 1 ? ' tweets' : ' tweet');

        return '<span class="jta-tweet-list-autorefresh-trigger-content">' + content + '</span>';
    };
    defaultTweetFeedDecorator = function (options) {
        // the default placeholder for the tweet feed is an unordered list
        return '<ul class="jta-tweet-list"></ul>';
    };
    defaultTweetDecorator = function (tweet, options) {
        // the default tweet is made of the optional user's profile image and the
        // tweet body inside a list item element
        var html = '';

        if (options._tweetFeedConfig.showProfileImages) {
            html += options.tweetProfileImageDecorator(tweet, options);
        }

        if (options.tweetBodyDecorator) {
            html += options.tweetBodyDecorator(tweet, options);
        }

        html += '<div class="jta-clear">&nbsp;</div>';

        return '<li class="jta-tweet-list-item">' + html + '</li>';
    };
    defaultTweetProfileImageDecorator = function (tweet, options) {
        // if tweet is a native retweet, use the retweet's profile
        var t = tweet.retweeted_status || tweet;

        // the default profile image decorator simply adds a link to the user's Twitter profile
        var screenName = t.user ? t.user.screen_name : false || t.from_user;
        var imageUrl = t.user ? t.user.profile_image_url : false || t.profile_image_url;

        var html =
			'<a class="jta-tweet-profile-image-link" href="http://twitter.com/' + screenName + '" target="_blank">' +
			'<img src="' + imageUrl + '" alt="' + screenName + '"' +
			(isAnywherePresent() ? '' : (' title="' + screenName + '"')) +
			'/>' +
			'</a>';

        return '<div class="jta-tweet-profile-image">' + html + '</div>';
    };
    defaultTweetBodyDecorator = function (tweet, options) {
        // the default tweet body contains the tweet text and the tweet's creation date
        var html = '';

        if (options.tweetTextDecorator) {
            html += options.tweetTextDecorator(tweet, options);
        }

        if (options.tweetAttributesDecorator) {
            html += options.tweetAttributesDecorator(tweet, options);
        }

        return '<div class="jta-tweet-body ' + (options._tweetFeedConfig.showProfileImages ? 'jta-tweet-body-list-profile-image-present' : '') + '">' + html + '</div>';
    };
    defaultTweetTextDecorator = function (tweet, options) {
        var tweetText = tweet.text;

        // if usernames should be visible and tweet is a native retweet, use
        // the original tweet text
        if (tweet.retweeted_status &&
			(
				options._tweetFeedConfig.showUserScreenNames ||
				options._tweetFeedConfig.showUserScreenNames == null ||
				options._tweetFeedConfig.showUserFullNames ||
				options._tweetFeedConfig.showUserFullNames == null
			)
		) {
            tweetText = tweet.retweeted_status.text;
        }

        // the default tweet text decorator optionally marks links, @usernames,
        // and #hashtags
        if (options.linkDecorator) {
            tweetText = options.linkDecorator(tweetText, options);
        }

        if (options.usernameDecorator) {
            tweetText = options.usernameDecorator(tweetText, options);
        }

        if (options.hashtagDecorator) {
            tweetText = options.hashtagDecorator(tweetText, options);
        }

        if (options._tweetFeedConfig.showUserScreenNames ||
			options._tweetFeedConfig.showUserFullNames ||
			tweet.retweeted_status &&
			(
				options._tweetFeedConfig.showUserScreenNames == null ||
				options._tweetFeedConfig.showUserFullNames == null
			)
		) {
            tweetText = options.tweetUsernameDecorator(tweet, options) + ' ' + tweetText;
        }

        return '<span class="jta-tweet-text">' + tweetText + '</span>';
    };
    defaultTweetUsernameDecorator = function (tweet, options) {
        // if tweet is a native retweet, use the retweet's profile
        var t = tweet.retweeted_status || tweet;
        var screenName = t.user ? t.user.screen_name : false || t.from_user;
        var fullName = t.user ? t.user.name : null;

        var htmlScreenName;
        if (screenName && (options._tweetFeedConfig.showUserScreenNames || (options._tweetFeedConfig.showUserScreenNames == null && tweet.retweeted_status))) {
            htmlScreenName =
				'<span class="jta-tweet-user-screen-name">' +
				'<a class="jta-tweet-user-screen-name-link" href="http://twitter.com/' + screenName + '" target="_blank">' +
				screenName +
				'</a>' +
				'</span>';
        }

        var htmlFullName;
        if (fullName && (options._tweetFeedConfig.showUserFullNames || (options._tweetFeedConfig.showUserFullNames == null && tweet.retweeted_status))) {
            htmlFullName =
				'<span class="jta-tweet-user-full-name">' +
				(htmlScreenName ? ' (' : '') +
				'<a class="jta-tweet-user-full-name-link" href="http://twitter.com/' + screenName + '" name="' + screenName + '" target="_blank">' +
				fullName +
				'</a>' +
				(htmlScreenName ? ')' : '') +
				'</span>';
        }

        var html = "";

        if (htmlScreenName) {
            html += htmlScreenName;
        }

        if (htmlFullName) {
            if (htmlScreenName) {
                html += ' ';
            }

            html += htmlFullName;
        }

        if (htmlScreenName || htmlFullName) {
            html =
				'<span class="jta-tweet-user-name">' +
				(tweet.retweeted_status ? 'RT ' : '') +
				html +
				'</span>';
        }

        return html;
    };
    defaultTweetAttributesDecorator = function (tweet, options) {
        var html = '';

        if (options.tweetTimestampDecorator ||
			options.tweetSourceDecorator ||
			options.tweetGeoLocationDecorator ||
			options.tweetInReplyToDecorator ||
			(tweet.retweeted_status && options.tweetRetweeterDecorator)
		) {
            html += '<span class="jta-tweet-attributes">';

            if (options.tweetTimestampDecorator) {
                html += options.tweetTimestampDecorator(tweet, options);
            }

            if (options.tweetSourceDecorator) {
                html += options.tweetSourceDecorator(tweet, options);
            }

            if (options.tweetGeoLocationDecorator) {
                html += options.tweetGeoLocationDecorator(tweet, options);
            }

            if (options.tweetInReplyToDecorator) {
                html += options.tweetInReplyToDecorator(tweet, options);
            }

            if (tweet.retweeted_status && options.tweetRetweeterDecorator) {
                html += options.tweetRetweeterDecorator(tweet, options);
            }

            html += '</span>';
        }

        return html;
    };
    defaultTweetTimestampDecorator = function (tweet, options) {
        // the default tweet timestamp decorator does a little bit of Twitter like formatting.

        // if tweet is a native retweet, use the retweet's timestamp
        var tw = tweet.retweeted_status || tweet;

        // reformat timestamp from Twitter, so IE is happy
        var createdAt = formatDate(tw.created_at);

        // format the timestamp by the tweetTimestampFormatter
        var tweetTimestamp = options.tweetTimestampFormatter(createdAt);
        var tweetTimestampTooltip = options.tweetTimestampTooltipFormatter(createdAt);

        var screenName = tw.user ? tw.user.screen_name : false || tw.from_user;
        var html =
			'<span class="jta-tweet-timestamp">' +
			'<a class="jta-tweet-timestamp-link" data-timestamp="' + createdAt +
			'" href="http://twitter.com/' + screenName + '/status/' + tw.id + '" target="_blank" title="' +
			tweetTimestampTooltip + '">' +
			tweetTimestamp +
			'</a>' +
			'</span>';

        return html;
    };
    defaultTweetTimestampTooltipFormatter = function (timeStamp) {
        var d = new Date(timeStamp);

        return d.toLocaleString();
    };
    defaultTweetTimestampFormatter = function (timeStamp) {
        var now = new Date();

        var diff = parseInt((now.getTime() - Date.parse(timeStamp)) / 1000);

        var tweetTimestamp = '';
        if (diff < 60) {
            tweetTimestamp += diff + ' sekund' + (diff == 1 ? '' : 'er') + ' sedan';
        }
        else if (diff < 3600) {
            var t = parseInt((diff + 30) / 60);
            tweetTimestamp += t + ' minut' + (t == 1 ? '' : 'er') + ' sedan';
        }
        else if (diff < 86400) {
            var t = parseInt((diff + 1800) / 3600);
            tweetTimestamp += t + ' timm' + (t == 1 ? 'e' : 'ar') + ' sedan';
        }
        else {
            var d = new Date(timeStamp);
            var period = 'AM';

            var hours = d.getHours();
            if (hours > 12) {
                hours -= 12;
                period = 'PM';
            }

            var mins = d.getMinutes();
            var minutes = (mins < 10 ? '0' : '') + mins;

            var monthName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

            tweetTimestamp += monthName[d.getMonth()] + ' ' + d.getDate();

            if (d.getFullYear() < now.getFullYear()) {
                tweetTimestamp += ', ' + d.getFullYear();
            }

            var t = parseInt((diff + 43200) / 86400);
            tweetTimestamp += ' (' + t + ' day' + (t == 1 ? '' : 's') + ' ago)';
        }

        return tweetTimestamp;
    };
    exTimestampFormatter = function (timeStamp) {
        var diff = parseInt((new Date().getTime() - Date.parse(timeStamp)) / 1000);

        var tweetTimestamp = '';
        if (diff < 60) {
            tweetTimestamp += 'less than a minute ago';
        }
        else if (diff < 3600) {
            var t = parseInt((diff + 30) / 60);
            tweetTimestamp += t + ' minute' + (t == 1 ? '' : 's') + ' ago';
        }
        else if (diff < 86400) {
            var t = parseInt((diff + 1800) / 3600);
            tweetTimestamp += 'about ' + t + ' hour' + (t == 1 ? '' : 's') + ' ago';
        }
        else {
            var t = parseInt((diff + 43200) / 86400);
            tweetTimestamp += 'about ' + t + ' day' + (t == 1 ? '' : 's') + ' ago';

            var d = new Date(timeStamp);
            var period = 'AM';

            var hours = d.getHours();
            if (hours > 12) {
                hours -= 12;
                period = 'PM';
            }

            var mins = d.getMinutes();
            var minutes = (mins < 10 ? '0' : '') + mins;

            tweetTimestamp += ' (' + hours + ':' + minutes + ' ' + period + ' ' + (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear() + ')';
        }

        return tweetTimestamp;
    };
    defaultTweetSourceDecorator = function (tweet, options) {
        // if tweet is a native retweet, use the retweet's source
        var tw = tweet.retweeted_status || tweet;

        var source = tw.source.replace(/\&lt\;/gi, '<').replace(/\&gt\;/gi, '>').replace(/\&quot\;/gi, '"');
        var html =
			'<span class="jta-tweet-source">' +
			' via ' +
			'<span class="jta-tweet-source-link">' +
			source +
			'</span>' +
			'</span>';

        return html;
    };
    defaultTweetGeoLocationDecorator = function (tweet, options) {
        var html = '';

        // if tweet is a native retweet, use the retweet's source
        var tw = tweet.retweeted_status || tweet;

        var q;
        if (tw.geo && tw.geo.coordinates) {
            q = tw.geo.coordinates.join();
        }
        else if (tw.place && tw.place.full_name) {
            q = tw.place.full_name;
        }

        if (q) {
            var location = 'here';
            if (tw.place && tw.place.full_name) {
                location = tw.place.full_name;
            }

            var link = 'http://maps.google.com/maps?q=' + q;

            html =
				'<span class="jta-tweet-location">' +
				' from ' +
				'<a class="jta-tweet-location-link" href="' + link + '" target="_blank">' +
				location +
				'</a>' +
				'</span>';
        }

        return html;
    };
    defaultTweetInReplyToDecorator = function (tweet, options) {
        // if tweet is a native retweet, use the retweet's source
        var tw = tweet.retweeted_status || tweet;

        var html = '';
        if (tw.in_reply_to_status_id && tw.in_reply_to_screen_name) {
            html =
				'<span class="jta-tweet-inreplyto">' +
				' ' +
				'<a class="jta-tweet-inreplyto-link" href="http://twitter.com/' + tw.in_reply_to_screen_name + '/status/' + tw.in_reply_to_status_id + '" target="_blank">' +
				'in reply to ' + tw.in_reply_to_screen_name +
				'</a>' +
				'</span>';
        }

        return html;
    };
    defaultTweetRetweeterDecorator = function (tweet, options) {
        var html = '';

        if (tweet.retweeted_status) {
            var screenName = tweet.user ? tweet.user.screen_name : false || tweet.from_user;
            var rtc = (tweet.retweeted_status.retweet_count || 0) - 1;

            var link =
				'<a class="jta-tweet-retweeter-link" href="http://twitter.com/' + screenName + '" target="_blank">' +
				screenName +
				'</a>';
            var rtcount = ' and ' + rtc + (rtc > 1 ? ' others' : ' other');
            html =
				'<br/>' +
				'<span class="jta-tweet-retweeter">' +
				'Retweeted by ' + link +
				(rtc > 0 ? rtcount : '') +
				'</span>';
        }

        return html;
    };
    defaultConnectButtonDecorator = function (options) {
        // the default placeholder for the @Anywhere ConnectButton
        return '<div class="jta-connect-button"></div>';
    };
    defaultLoginInfoDecorator = function (options) {
        // the default placeholder for the LoginInfo
        return '<div class="jta-login-info"></div>';
    };
    defaultLoginInfoContentDecorator = function (options, T) {
        // the default markup of the LoginInfo content: the user's profile image, the
        // user's screen_name and a "button" to sign out
        var html = '';

        if (T.isConnected()) {
            var screenName = T.currentUser.data('screen_name');
            var imageUrl = T.currentUser.data('profile_image_url');

            html =
				'<div class="jta-login-info-profile-image">' +
				'<a href="http://twitter.com/' + screenName + '" target="_blank">' +
				'<img src="' + imageUrl + '" alt="' + screenName + '" title="' + screenName + '"/>' +
				'</a>' +
				'</div>' +
				'<div class="jta-login-info-block">' +
				'<div class="jta-login-info-screen-name">' +
				'<a href="http://twitter.com/' + screenName + '" target="_blank">' + screenName + '</a>' +
				'</div>' +
				'<div class="jta-login-info-sign-out">' +
				'Sign out' +
				'</div>' +
				'</div>' +
				'<div class="jta-clear">&nbsp;</div>'
				;
        }

        return html;
    };
    defaultFollowButtonDecorator = function (options) {
        // the default placeholder for the @Anywhere FollowButton
        return '<div class="jta-follow-button"></div>';
    };
    defaultTweetBoxDecorator = function (options) {
        // the default placeholder for the @Anywhere TweetBox
        return '<div class="jta-tweet-box"></div>';
    };
    defaultLinkDecorator = function (text, options) {
        // the regex to markup links
        return text.replace(/((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi, '<a href="$1" class="jta-tweet-a jta-tweet-link" target="_blank" rel="nofollow">$1<\/a>');
    };
    defaultUsernameDecorator = function (text, options) {
        // the regex to markup @usernames. if @Anywhere is present the task is left to
        // them
        return isAnywherePresent() ? text : text.replace(/@([a-zA-Z0-9_]+)/gi, '@<a href="http://twitter.com/$1" class="jta-tweet-a twitter-anywhere-user" target="_blank" rel="nofollow">$1<\/a>');
    };
    defaultHashtagDecorator = function (text, options) {
        // the regex to markup #hashtags
        return text.replace(/#([a-zA-Z0-9_]+)/gi, '<a href="http://search.twitter.com/search?q=%23$1" class="jta-tweet-a jta-tweet-hashtag" title="#$1" target="_blank" rel="nofollow">#$1<\/a>');
    };
    defaultLoadingDecorator = function (options) {
        // the default loading decorator simply says: loading ...
        return '<li class="jta-loading">Laddar senaste tweeten ...</li>';
    };
    defaultErrorDecorator = function (errorText, options) {
        // the default error decorator shows the error message
        return '<li class="jta-error">ERROR: ' + errorText + '</li>';
    };
    defaultNoDataDecorator = function (options) {
        // the default no-data decorator simply says: No more data
        return '<li class="jta-nodata">No more data</li>';
    };

    defaultTweetFilter = function (tweet, options) {
        return true;
    };

    defaultTweetVisualizer = function (tweetFeedElement, tweetElement, inserter, options) {
        // insert (append/prepend) the tweetElement to the tweetFeedElement
        tweetFeedElement[inserter](tweetElement);
    };
    defaultLoadingIndicatorVisualizer = function (tweetFeedElement, loadingIndicatorElement, options, callback) {
        defaultVisualizer(tweetFeedElement, loadingIndicatorElement, 'append', 'fadeIn', 600, 'fadeOut', 200, callback);
    };
    defaultAutorefreshTriggerVisualizer = function (tweetFeedElement, triggerElement, options, callback) {
        defaultVisualizer(tweetFeedElement, triggerElement, 'prepend', 'slideDown', 600, 'fadeOut', 200, callback);
    };
    defaultVisualizer = function (container, element, inserter, effectIn, durationIn, effectOut, durationOut, callback) {
        // if param container is null element has to be removed from
        // the DOM, else element has to be inserted in container

        // if param callback is not null, the callback function must be called
        // in any case, if the visualizer is done

        var cb = function () {
            if (callback) {
                callback();
            }
        };

        if (container) {
            element.hide();
            container[inserter](element);
            element[effectIn](durationIn, cb);
        }
        else {
            element[effectOut](durationOut, function () {
                element.remove();
                cb();
            });
        }
    };

    defaultOnDataRequestHandler = function (stats, options) {
        return true;
    };
    defaultOnRateLimitDataHandler = function (stats, options) {
    };

    updateLoginInfoElement = function (options, T) {
        // update the content of the LoginInfo element
        if (options._loginInfoElement && options.loginInfoContentDecorator) {
            options._loginInfoElement.children().remove();
            options._loginInfoElement.append(options.loginInfoContentDecorator(options, T));
            $(options._baseSelector + ' .jta-login-info-sign-out').bind('click', function () {
                twttr.anywhere.signOut();
            });
        }
    };
    getFeedUrl = function (options, flPaging) {
        // create the Twitter API URL based on the configuration options
        var url = ('https:' == document.location.protocol ? 'https:' : 'http:');

        if (options.searchParams) {
            url += '//search.twitter.com/search.json?' +
				((options.searchParams instanceof Array) ? options.searchParams.join('&') : options.searchParams) +
				'&rpp=100';
        }
        else if (options.list) {
            url += '//api.twitter.com/1/' + options.username + '/lists/' + options.list + '/statuses.json?per_page=20';
        }
        else {
            url += '//api.twitter.com/1/statuses/user_timeline.json?screen_name=' + options.username + '&count=20';
            if (options._tweetFeedConfig.includeRetweets)
                url += '&include_rts=true';
        }

        if (flPaging) {
            url +=
				(options._tweetFeedConfig._maxId > 0 ? '&max_id=' + options._tweetFeedConfig._maxId : '') +
				'&page=' + options._tweetFeedConfig._pageParam;
        }

        url += '&callback=?';

        return url;
    };
    isAnywherePresent = function () {
        // check, if @Anywhere is present
        return typeof (twttr) != 'undefined';
    };
    clearTweetFeed = function (options) {
        if (options._tweetFeedElement) {
            options._tweetFeedElement.empty();
        }
    };
    populateTweetFeed = function (options) {
        // if a tweet feed is to be displayed, get the tweets and show them
        if (options.tweetDecorator && options._tweetFeedElement) {
            getPagedTweets(options, function (tweets, options) {
                if (options._tweetFeedConfig._clearBeforePopulate) {
                    clearTweetFeed(options);
                }

                hideLoadingIndicator(options, function () {
                    // process the tweets
                    $.each(tweets, function (idx, tweet) {
                        // decorate the tweet and give it to the tweet visualizer
                        options.tweetVisualizer(
							options._tweetFeedElement,
							$(options.tweetDecorator(tweet, options)),
							'append',
							options
						);
                    });

                    if (options._tweetFeedConfig._noData && options.noDataDecorator && !options._tweetFeedConfig._noDataElement) {
                        options._tweetFeedConfig._noDataElement = $(options.noDataDecorator(options));
                        options._tweetFeedElement.append(options._tweetFeedConfig._noDataElement);
                    }

                    if (options._tweetFeedConfig._clearBeforePopulate) {
                        options._tweetFeedElement.scrollTop(0);
                    }

                    addHovercards(options);
                });
            });
        }
    };
    populateTweetFeed2 = function (options) {
        if (options._tweetFeedElement && options._autorefreshTweetsCache.length > 0) {
            if (options._tweetFeedConfig.autorefresh.mode == 'trigger-insert') {
                if (options._tweetFeedConfig.autorefresh._triggerElement) {
                    if (options.tweetFeedAutorefreshTriggerContentDecorator) {
                        options._tweetFeedConfig.autorefresh._triggerElement.html(
							options.tweetFeedAutorefreshTriggerContentDecorator(options._autorefreshTweetsCache.length, options)
						);
                    }
                }
                else {
                    if (options.tweetFeedAutorefreshTriggerDecorator) {
                        options._tweetFeedConfig.autorefresh._triggerElement =
							$(options.tweetFeedAutorefreshTriggerDecorator(options._autorefreshTweetsCache.length, options));
                        options._tweetFeedConfig.autorefresh._triggerElement.bind('click', function () {
                            options.autorefreshTriggerVisualizer(
								null,
								options._tweetFeedConfig.autorefresh._triggerElement,
								options,
								function () {
								    insertTriggerTweets(options);
								}
							);
                            options._tweetFeedConfig.autorefresh._triggerElement = null;
                        });

                        options.autorefreshTriggerVisualizer(options._tweetFeedElement, options._tweetFeedConfig.autorefresh._triggerElement, options);
                    }
                }
            }
            else {
                insertTriggerTweets(options);
            }
        }
    };
    insertTriggerTweets = function (options) {
        // populate the tweet feed with tweets from the autorefresh cache
        if (options.tweetDecorator && options._autorefreshTweetsCache.length > 0) {
            // process the autorefresh cache
            while (options._autorefreshTweetsCache.length > 0) {
                // get the last tweet and remove it from the autorefresh cache
                var tweet = options._autorefreshTweetsCache.pop();

                // put that tweet on top of the tweets cache
                options._tweetsCache.unshift(tweet);

                // adjust paging offset
                options._tweetFeedConfig.paging._offset++;

                // decorate the tweet and give it to the tweet visualizer
                options.tweetVisualizer(
					options._tweetFeedElement,
					$(options.tweetDecorator(tweet, options)),
					'prepend',
					options
				);
            }

            addHovercards(options);
        }
    };
    addHovercards = function (options) {
        if (isAnywherePresent()) {
            // if @Anywhere is present, append Hovercards to @username and
            // profile images
            twttr.anywhere(function (T) {
                T(options._baseSelector + ' .jta-tweet-list').hovercards({ expanded: options._tweetFeedConfig.expandHovercards });
                T(options._baseSelector + ' .jta-tweet-profile-image img').hovercards(
				{
				    expanded: options._tweetFeedConfig.expandHovercards,
				    username: function (node) { return node.alt; }
				});
                T(options._baseSelector + ' .jta-tweet-retweeter-link').hovercards(
				{
				    expanded: options._tweetFeedConfig.expandHovercards,
				    username: function (node) { return node.text; }
				});
                T(options._baseSelector + ' .jta-tweet-user-screen-name-link').hovercards(
				{
				    expanded: options._tweetFeedConfig.expandHovercards,
				    username: function (node) { return node.text; }
				});
                T(options._baseSelector + ' .jta-tweet-user-full-name-link').hovercards(
				{
				    expanded: options._tweetFeedConfig.expandHovercards,
				    username: function (node) { return node.name; }
				});
            });
        }
    };
    populateAnywhereControls = function (options) {
        if (isAnywherePresent()) {
            twttr.anywhere(function (T) {
                // optionally add an @Anywhere TweetBox
                if (options.tweetBoxDecorator) {
                    T(options._baseSelector + ' .jta-tweet-box').tweetBox(options._tweetBoxConfig);
                }

                // optionally add an @Anywhere FollowButton
                if (options.followButtonDecorator) {
                    T(options._baseSelector + ' .jta-follow-button').followButton(options.username);
                }

                // optionally add an @Anywhere ConnectButton
                if (options.connectButtonDecorator) {
                    var o = $.extend(
					{
					    authComplete: function (user) {
					        // display/update login infos on connect/signin event
					        updateLoginInfoElement(options, T);
					    },
					    signOut: function () {
					        // display/update login infos on signout event
					        updateLoginInfoElement(options, T);
					    }
					}, options._connectButtonConfig);

                    T(options._baseSelector + ' .jta-connect-button').connectButton(o);

                    // display/update login infos
                    updateLoginInfoElement(options, T);
                }
            });
        }
    };
    bindEventHandlers = function (options) {
        if (options.tweetFeedControlsDecorator) {
            if (options._tweetFeedConfig.paging.mode == 'prev-next') {
                $(options._baseSelector + ' .jta-tweet-list-controls-button-prev').bind('click', function () {
                    if (!isLoading(options) && options._tweetFeedConfig.paging._offset > 0) {
                        prevPage(options, true);
                    }
                });
                $(options._baseSelector + ' .jta-tweet-list-controls-button-next').bind('click', function () {
                    if (!isLoading(options)) {
                        nextPage(options, true);
                    }
                });
            }
            else if (options._tweetFeedConfig.paging.mode == 'endless-scroll') {
                options._tweetFeedElement.bind("scroll", function () {
                    if (!isLoading(options) && ($(this)[0].scrollHeight - $(this).scrollTop() == $(this).outerHeight())) {
                        nextPage(options, false);
                    }
                });
            }
            else {
                $(options._baseSelector + ' .jta-tweet-list-controls-button-more').bind('click', function () {
                    if (!isLoading(options)) {
                        nextPage(options, false);
                    }
                });
            }
        }
    };
    nextPage = function (options, flClear) {
        doPage(options, flClear, Math.min(options._tweetFeedConfig.paging._offset + options._tweetFeedConfig.paging._limit, options._tweetsCache.length));
    };
    prevPage = function (options, flClear) {
        doPage(options, flClear, Math.max(0, options._tweetFeedConfig.paging._offset - options._tweetFeedConfig.paging._limit));
    };
    doPage = function (options, flClear, newOffset) {
        options._tweetFeedConfig.paging._offset = newOffset;
        options._tweetFeedConfig._clearBeforePopulate = flClear;

        populateTweetFeed(options);
    };
    startAutorefresh = function (options) {
        if (options._tweetFeedConfig.autorefresh.mode != 'none' &&
			options._tweetFeedConfig.paging.mode != 'prev-next' &&
			options._tweetFeedConfig.autorefresh.duration != 0 &&
			(
				options._tweetFeedConfig.autorefresh.duration < 0 ||
				(new Date().getTime() - options._tweetFeedConfig.autorefresh._startTime) <= options._tweetFeedConfig.autorefresh.duration * 1000
			)
		) {
            window.setTimeout(function () { processAutorefresh(options); }, options._tweetFeedConfig.autorefresh.interval * 1000);
        }
    };
    stopAutorefresh = function (options) {
        options._tweetFeedConfig.autorefresh.duration = 0;
    };
    processAutorefresh = function (options) {
        if (options._tweetFeedConfig.autorefresh.duration != 0) {
            // load the data ...
            getRateLimitedData(options, true, getFeedUrl(options, false), function (data, options) {
                // reverse the sequence of the autorefresh tweets ...
                var tweets = (data.results || data).slice(0);
                tweets.reverse();

                // ...then process them
                $.each(tweets, function (idx, tweet) {
                    // if this tweet is already in the standard tweets cache, ignore
                    if (!isTweetInCache(tweet, options)) {
                        // optionally filter tweet ...
                        if (options.tweetFilter(tweet, options)) {
                            // ... then put it to the top of the autorefresh cache
                            options._autorefreshTweetsCache.unshift(tweet);
                        }
                    }
                });

                populateTweetFeed2(options);
            });

            // restart autorefresh
            startAutorefresh(options);
        }
    };
    startTimestampRefresh = function (options) {
        if (
			options.tweetTimestampDecorator &&
			typeof (options._tweetFeedConfig.showTimestamp) == 'object' &&
			options._tweetFeedConfig.showTimestamp.refreshInterval > 0
		) {
            window.setTimeout(function () { processTimestampRefresh(options); }, options._tweetFeedConfig.showTimestamp.refreshInterval * 1000);
        }
    };
    processTimestampRefresh = function (options) {
        $.each(options._tweetFeedElement.find('.jta-tweet-timestamp-link'), function (idx, element) {
            var dataTimestamp = $(element).attr('data-timestamp');

            $(element).html(options.tweetTimestampFormatter(dataTimestamp));
        });

        startTimestampRefresh(options);
    };
    isTweetInCache = function (tweet, options) {
        var l = options._tweetsCache.length;

        for (var i = 0; i < l; i++) {
            if (tweet.id == options._tweetsCache[i].id) {
                return true;
            }
        }

        return false;
    };
    showLoadingIndicator = function (options) {
        if (options._tweetFeedElement && options.loadingDecorator && !options._loadingIndicatorElement) {
            options._loadingIndicatorElement = $(options.loadingDecorator(options));
            options.loadingIndicatorVisualizer(options._tweetFeedElement, options._loadingIndicatorElement, options, null);
            options._tweetFeedElement.scrollTop(1000000);
        }
    };
    hideLoadingIndicator = function (options, callback) {
        if (options._loadingIndicatorElement) {
            options.loadingIndicatorVisualizer(null, options._loadingIndicatorElement, options, callback);
            options._loadingIndicatorElement = null;
        }
        else {
            if (callback) {
                callback();
            }
        }
    };
    isLoading = function (options) {
        return options._loadingIndicatorElement != null;
    };
    formatDate = function (dateStr) {
        return dateStr.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3');
    };
    validateRange = function (num, lo, hi) {
        if (num < lo)
            num = lo;

        if (num > hi)
            num = hi;

        return num;
    };
    showError = function (options, errorText) {
        if (options.errorDecorator && options._tweetFeedElement) {
            options._tweetFeedElement.append(options.errorDecorator(errorText, options));
        }
    };
    getPagedTweets = function (options, callback) {
        options._tweetFeedConfig._recLevel = 0;

        getRecPagedTweets(options, options._tweetFeedConfig.paging._offset, options._tweetFeedConfig.paging._limit, callback);
    };
    getRecPagedTweets = function (options, offset, limit, callback) {
        ++options._tweetFeedConfig._recLevel;

        if (offset + limit <= options._tweetsCache.length ||
    		options._tweetFeedConfig._recLevel > 3 ||
    		options._tweetFeedConfig._noData
    	) {
            // if the requested data is already cached or the max. no. of
            // consecutive API calls is reached, use the records

            if (offset + limit > options._tweetsCache.length) {
                limit = Math.max(0, options._tweetsCache.length - offset);
            }

            var tweets = [];

            for (var i = 0; i < limit; i++) {
                tweets[i] = options._tweetsCache[offset + i];
            }

            callback(tweets, options);
        }
        else {
            // ... if not, load the data, fill the cache and try again
            ++options._tweetFeedConfig._pageParam;

            getRateLimitedData(options, false, getFeedUrl(options, true), function (data, options) {
                var tweets = data.results || data;

                if (tweets.length == 0) {
                    options._tweetFeedConfig._noData = true;
                }
                else {
                    $.each(tweets, function (idx, tweet) {
                        // save the first tweet id for subsequent paging requests
                        if (options._tweetFeedConfig._maxId <= 0) {
                            options._tweetFeedConfig._maxId = tweet.id;
                        }

                        // optionally filter tweet ...
                        if (options.tweetFilter(tweet, options)) {
                            // then put it into the cache
                            options._tweetsCache.push(tweet);
                        }
                    });
                }

                getRecPagedTweets(options, offset, limit, callback);
            });
        }
    };
    getRateLimitedData = function (options, flAutorefresh, url, callback) {
        getRateLimit(options, function (rateLimit) {
            if (rateLimit && rateLimit.remaining_hits <= 0) {
                options._stats.rateLimitPreventionCount++;
                hideLoadingIndicator(options, null);
                return;
            }

            getData(options, flAutorefresh, url, callback);
        });
    };
    getData = function (options, flAutorefresh, url, callback) {
        options._stats.dataRequestCount++;

        if (!options.onDataRequestHandler(options._stats, options)) {
            hideLoadingIndicator(options, null);
            return;
        }

        if (!flAutorefresh) {
            showLoadingIndicator(options);
        }

        $.getJSON
		(url, function (data) {
		    if (data.error) {
		        // in case of an error, display the error message
		        showError(options, data.error);
		    }
		    else {
		        callback(data, options);
		    }
		});
    };
    getRateLimit = function (options, callback) {
        $.getJSON
		("http://api.twitter.com/1/account/rate_limit_status.json?callback=?", function (rateLimit) {
		    options._stats.rateLimit = rateLimit;

		    options.onRateLimitDataHandler(options._stats, options);

		    callback(rateLimit);
		});
    };
})(jQuery);
$(document).ready(function () {


    if (location.href.indexOf("#") != -1) {
        var hash = location.href.substr(location.href.indexOf("#"));
        if (hash == '#video') {
            $('#control1').removeClass("active");
            $('#control2').addClass("active");

            var newActiveH3pos = $('#slidermenu ul li.active h3').position();
            $('#sliderArrow').animate({
                top: newActiveH3pos.top
            }, 200);

            $('.sled').animate({
                marginLeft: '-650px'
            }, 1000);


        }
    }



    $('#tweet').jTweetsAnywhere({
        username: 'nyhetsbrev',
        count: 1,
        showFollowButton: false,
        showTimestamp: false
    });

    $('#startflash').flash({
        // test.swf is the flash document
        swf: '/files/SWF/indexflash.swf',
        height: 344,
        width: 650
    });
    $('#introflash').flash({
        // test.swf is the flash document
        swf: '/files/SWF/main.swf',
        height: 344,
        width: 650
    });

    $('#varfornyhetsbrevflash').flash({
        //  varfornyhetsbrev.swf is the flash document
        swf: '/files/SWF/varfornyhetsbrev.swf',
        height: 344,
        width: 650
    });

    var activeH3pos = $('#slidermenu ul li.active h3').offset();

    //$('#sliderArrow').css({ 'left': (activeH3pos.left - 62), 'top': activeH3pos.top });

    $('#slidermenu ul li.active p').show();

    $('#slidermenu ul li').click(function () {

        $('#slidermenu ul li').removeClass('active');
        $('#slidermenu ul li p').hide();
        $(this).addClass('active');
        $('#slidermenu ul li.active p').show();

        var newActiveH3pos = $('#slidermenu ul li.active h3').position();
        $('#sliderArrow').animate({
            top: newActiveH3pos.top
        }, 200);

        $('#absoluteRibbon').hide();

        if ($(this).attr('id') == 'control1') {
            $('.sled').animate({
                marginLeft: '0px'
            }, 1000);

        }
        else if ($(this).attr('id') == 'control2') {
            $('.sled').animate({
                marginLeft: '-650px'
            }, 1000);

        }
        else if ($(this).attr('id') == 'control3') {
            $('.sled').animate({
                marginLeft: '-1300px'
            }, 1000);
        }
        else if ($(this).attr('id') == 'control4') {
            $('.sled').animate({
                marginLeft: '-1950px'
            }, 1000, function () { $('#absoluteRibbon').show(); });
        }
    });

    if ($('.sliderBox').find('div#thanks').length > 0) {
        $('.sled').animate({
            marginLeft: '-1950px'
        }, 1000, function () { $('#absoluteRibbon').show(); });
    }
});
var sendButtonPostBack = "__doPostBack('ctl00$cphMiddle$sendButton','');";


