/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/9/2009
 * @author Ariel Flesler
 * @version 1.4.1
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function($){var m=$.scrollTo=function(b,h,f){$(window).scrollTo(b,h,f)};m.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1};m.window=function(b){return $(window).scrollable()};$.fn.scrollable=function(){return this.map(function(){var b=this,h=!b.nodeName||$.inArray(b.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!h)return b;var f=(b.contentWindow||b).document||b.ownerDocument||b;return $.browser.safari||f.compatMode=='BackCompat'?f.body:f.documentElement})};$.fn.scrollTo=function(l,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};if(l=='max')l=9e9;a=$.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=$(k),d=l,p,g={},q=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px)?$/.test(d)){d=n(d);break}d=$(d,this);case'object':if(d.is||d.style)p=(d=$(d)).offset()}$.each(a.axis.split(''),function(b,h){var f=h=='x'?'Left':'Top',i=f.toLowerCase(),c='scroll'+f,r=k[c],s=h=='x'?'Width':'Height';if(p){g[c]=p[i]+(q?0:r-o.offset()[i]);if(a.margin){g[c]-=parseInt(d.css('margin'+f))||0;g[c]-=parseInt(d.css('border'+f+'Width'))||0}g[c]+=a.offset[i]||0;if(a.over[i])g[c]+=d[s.toLowerCase()]()*a.over[i]}else g[c]=d[i];if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],u(s));if(!b&&a.queue){if(r!=g[c])t(a.onAfterFirst);delete g[c]}});t(a.onAfter);function t(b){o.animate(g,j,a.easing,b&&function(){b.call(this,l,a)})};function u(b){var h='scroll'+b;if(!q)return k[h];var f='client'+b,i=k.ownerDocument.documentElement,c=k.ownerDocument.body;return Math.max(i[h],c[h])-Math.min(i[f],c[f])}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);

/**
 * jQuery.LocalScroll - Animated scrolling navigation, using anchors.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/11/2009
 * @author Ariel Flesler
 * @version 1.2.7
 **/
;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('<a> </a>').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);

/**
 * jQuery.SerialScroll - Animated scrolling of series
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 06/14/2009
 * @author Ariel Flesler
 * @version 1.2.2
 * http://flesler.blogspot.com/2008/02/jqueryserialscroll.html
 **/
;(function(a){var b=a.serialScroll=function(c){return a(window).serialScroll(c)};b.defaults={duration:1e3,axis:"x",event:"click",start:0,step:1,lock:!0,cycle:!0,constant:!0};a.fn.serialScroll=function(c){return this.each(function(){var t=a.extend({},b.defaults,c),s=t.event,i=t.step,r=t.lazy,e=t.target?this:document,u=a(t.target||this,e),p=u[0],m=t.items,h=t.start,g=t.interval,k=t.navigation,l;if(!r){m=d()}if(t.force){f({},h)}a(t.prev||[],e).bind(s,-i,q);a(t.next||[],e).bind(s,i,q);if(!p.ssbound){u.bind("prev.serialScroll",-i,q).bind("next.serialScroll",i,q).bind("goto.serialScroll",f)}if(g){u.bind("start.serialScroll",function(v){if(!g){o();g=!0;n()}}).bind("stop.serialScroll",function(){o();g=!1})}u.bind("notify.serialScroll",function(x,w){var v=j(w);if(v>-1){h=v}});p.ssbound=!0;if(t.jump){(r?u:d()).bind(s,function(v){f(v,j(v.target))})}if(k){k=a(k,e).bind(s,function(v){v.data=Math.round(d().length/k.length)*k.index(this);f(v,this)})}function q(v){v.data+=h;f(v,this)}function f(B,z){if(!isNaN(z)){B.data=z;z=p}var C=B.data,v,D=B.type,A=t.exclude?d().slice(0,-t.exclude):d(),y=A.length,w=A[C],x=t.duration;if(D){B.preventDefault()}if(g){o();l=setTimeout(n,t.interval)}if(!w){v=C<0?0:y-1;if(h!=v){C=v}else{if(!t.cycle){return}else{C=y-v-1}}w=A[C]}if(!w||t.lock&&u.is(":animated")||D&&t.onBefore&&t.onBefore(B,w,u,d(),C)===!1){return}if(t.stop){u.queue("fx",[]).stop()}if(t.constant){x=Math.abs(x/i*(h-C))}u.scrollTo(w,x,t).trigger("notify.serialScroll",[C])}function n(){u.trigger("next.serialScroll")}function o(){clearTimeout(l)}function d(){return a(m,p)}function j(w){if(!isNaN(w)){return w}var x=d(),v;while((v=x.index(w))==-1&&w!=p){w=w.parentNode}return v}})}})(jQuery);


//////////////////////////////////////
//
// jQuery URL Toolbox *beta*
// Author: Mark Perkins - mark@allmarkedup.com
// See http://allmarkedup.com/journal/2009/10/jquery-url-toolbox-beta/ for more information.
//
//////////////////////////////////////


(function($){
	
	// set up a few constants & shortcuts
	var loc = document.location,
		tag2attr = {
		    a		: 'href',
		    img		: 'src',
		    form	: 'action',
		    base	: 'href',
		    script	: 'src',
		    iframe	: 'src',
		    link	: 'href'
		};
		
	// a few helper functions
	var isStr = function( item ) { return typeof item === 'string'; };
	var isObj = function( item ) { return typeof item === 'object'; };
	var isfunc = function( item ) { return typeof item === 'function'; };
	
	var isGetter = function( args ) { return ( args.length == 1 && ! isObj(args[0]) ); }
	var isSetter = function( args ) { return ( args.length >= 2 || (args.length == 1 && isObj(args[0])) ); }
	
	var stripQ = function( str ) { return str.replace(/\?.*$/, ''); }
	var stripH = function( str ) { return str.replace(/^#/, ''); }
	
	// split up a query sting
	function splitQuery( string )
	{
		var ret = {},
		seg = string.replace(/^\?/,'').split('&'),
		len = seg.length, i = 0, s;
		for (;i<len;i++)
		{
			if (!seg[i]) { continue; }
			s = seg[i].split('=');
			ret[s[0]] = s[1];
		}
		return ret;
	}
	
	// reconstructs a query string from an object of key:value pairs
	var combineQuery = function( params, prefixQM )
	{
		var queryString = ( prefixQM === true ) ? '?' : '';
		for ( i in params ) queryString += i+'='+params[i]+'&';
		return queryString.slice(0, -1);
	};
	
	// reconstructs a path string from an array of parts
	var combinePath = function( segments )
	{
		return segments.join('/');
	};
	
	function splitHashSegments( hash )
	{
		if ( hash.indexOf('=') === -1 )
		{
			if ( hash.charAt(hash.length-1) == '/' ) hash = hash.slice(0, -1);
			return hash.replace(/^\//,'').split('/');	
		} 
		return null;
	}
	
	function splitHashParams( hash )
	{
		if ( hash.indexOf('=') !== -1 ) return splitQuery( hash );
		return null;
	}
	
	// utility function to get tag name of $ objects
	var getTagName = function( elm )
	{
		var tg = $(elm).get(0).tagName;
		if ( tg !== undefined ) return tg.toLowerCase();
		return tg;
	}
	
	var throwParserError = function( msg )
	{
		if ( msg === undefined ) msg = 'url parser error';
		// console.log( msg ); 
	};
	
	var getHost = function( hostname, port )
	{
		// deals with non-standard port name issues, mostly in safari
		var portRegex = new RegExp( ':'+port ); // need to strip the non-standard ports out of safari
		return hostname.replace( portRegex, '' );
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////

	// create :internal and :external URL filters	
	
	$.extend($.expr[':'],{
	    external : function( elm, i, m )
		{
			var tagName = elm.tagName;
	
			if ( tagName !== undefined )
			{
				var tg = tagName.toLowerCase();
				var attr = tag2attr[tg];
				if ( elm[attr] )
				{
					if ( tg !== 'a' )
					{
						var a = document.createElement('a');
    					a.href = elm[attr];
					}
					else var a = elm;
					return a.hostname && getHost( a.hostname, a.port ) !== getHost( loc.hostname, loc.port );
				}
			}
			return false;
	    },
		internal : function( elm, i, m )
		{
			var tagName = elm.tagName;
			if ( tagName !== undefined )
			{
				var tg = tagName.toLowerCase();
				var attr = tag2attr[tg];
				if ( elm[attr] )
				{
					if ( tg !== 'a' )
					{
						var a = document.createElement('a');
    					a.href = elm[attr];
					}
					else var a = elm;
					return a.hostname && getHost( a.hostname, a.port ) === getHost( loc.hostname, loc.port );
				}
			}
			return false;
	    }
	});
	
	/////// two essentially analagous functions to return an activeUrl object (just in different ways) ////////
	
	// this one is for when you just want to use a manually passed in URL string
	$.url = function( urlString )
	{
		return new activeUrl( urlString );
	};
	
	// this one is when using DOM objects as the source for the URL
	$.fn.url = function()
	{
		if ( this.size() > 1 )
		{
			// more than one object, return a collection of activeUrls
			var activeUrls = {};
		
			this.each(function( i ){
				activeUrls[i] = new activeUrl( $(this) );
			});
		
			return activeUrls;
		}
		else
		{
			// just one item, return just the one active url
			return new activeUrl( this );
		}
	};
	
	// watch the URL, basically implement history and ajax bookmarking functionality
	$.observeUrl = function( delay )
	{	
		if ( delay === undefined ) delay = 100;
		
		var currentHash,
			historyIframeSrc,
			backStack,
			forwardStack,
			lastHistoryLength,
			dontCheck,
			isIE = $.browser.msie,
			isSafari = $.browser.safari,
			silentHashChange = false,
			historyCheckInterval;
	
		var historyInit = function()
		{
			currentHash = stripQ( loc.hash );
			
			if ( isIE )
			{
				// To stop the callback firing twice during initilization if no hash present
				if ( currentHash == '' ) { currentHash = '#'; }
		
				// add hidden iframe for IE
				$("body").prepend('<iframe id="browser_history" style="display: none;" src="'+loc.href+'"></iframe>');
				
				setIframeHash( currentHash );
			}
			else if ( $.browser.safari )
			{
				// etablish back/forward stacks
				backStack = [];
				backStack.length = history.length;
				forwardStack = [];
				lastHistoryLength = history.length;
			
				isFirst = true;
			}
		
			if ( currentHash ) hashChange( stripH( currentHash ) );

			historyCheckInterval = setInterval( historyCheck, delay );
		};
	
		var addHistory = function( hash )
		{
			// This makes the looping function do something
			backStack.push( hash );
			forwardStack.length = 0; // clear forwardStack (true click occured)
			isFirst = true;
		};
	
		var historyCheck = function()
		{
			if ( isIE )
			{
				// On IE, check for location.hash of iframe
				var ihistory = $("#browser_history")[0];
				var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
				var hash = stripQ( iframe.location.hash );
					
				if( hash != currentHash)
				{
					loc.hash = hash;
					currentHash = hash;
					hashChange( stripH( hash ) );
				}
				else if ( stripH(currentHash) != stripH(loc.hash) )
				{
					// this is for if the url is altered manually
					historyLoad( stripH(loc.hash) );
				}
			}
			else if ( isSafari )
			{
				if ( lastHistoryLength == history.length && backStack.length > lastHistoryLength)
				{
					backStack.shift();
				}
				if ( !dontCheck )
				{
					var historyDelta = history.length - backStack.length;
					lastHistoryLength = history.length;
				
					if ( historyDelta )
					{ 
						// back or forward button has been pushed
						isFirst = false;
						if (historyDelta < 0)
						{ 
							// back button has been pushed
							// move items to forward stack
							for (var i = 0; i < Math.abs(historyDelta); i++) forwardStack.unshift(backStack.pop());
						}
						else
						{ 
							// forward button has been pushed
							// move items to back stack
							for (var i = 0; i < historyDelta; i++) backStack.push(forwardStack.shift());
						}
						var cachedHash = backStack[backStack.length - 1];
						if ( cachedHash != undefined )
						{
							currentHash = stripQ( loc.hash );
							hashChange( cachedHash );
						}
					}
					else if (backStack[backStack.length - 1] == undefined && !isFirst)
					{
						// back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
						// document.URL doesn't change in Safari
						if (loc.hash)
						{
							// var hash = location.hash;
							hashChange( stripH( loc.hash ) );
						}
						else
						{
							// var hash = '';
							hashChange('');
						}
						isFirst = true;
					}
				}
			}
			else
			{
				// otherwise, check for location.hash
				var hash = stripQ( loc.hash );
				if( hash != currentHash )
				{
					currentHash = hash;
					hashChange( stripH(hash) );
				}
			}
		};
	
		var historyLoad = function( hash )
		{
			hash = decodeURIComponent( stripQ( hash ) );
		
			if ( $.browser.safari )
			{
				newHash = hash;
			}
			else
			{
				newHash = '#' + hash;
				loc.hash = newHash;
			}
			
			currentHash = newHash;
		
			if ( isIE )
			{
				setIframeHash( newHash );
				lastHistoryLength = history.length;
				hashChange( hash );
			}
			else if ( isSafari )
			{
				dontCheck = true;
				addHistory( hash );
				window.setTimeout( function(){ dontCheck = false; }, 200 );
				hashChange( hash );
				loc.hash = newHash;
			}
			else
			{
			  hashChange( hash );
			}
		};
		
		var setIframeHash = function( hash )
		{
			var ihistory = $("#browser_history")[0];
			var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
			iframe.open();
			iframe.close();
			iframe.location.hash = hash;
		};
		
	 	var hashChange = function()
		{
			if ( ! silentHashChange ) $(document).trigger( 'hash:change', stripH( loc.hash ) );
			silentHashChange = false;
		};
		
		$(document).bind('hash:unwatch', function(){
			
			// stops the has:change being triggered for 1 event
			silentHashChange = true;

		});

		historyInit();
	};
		
	/////// guts of the parser /////////////////////////////////////////////////////////////
	
	function parseUrl( url )
	{
    	var a =  document.createElement('a');
    	a.href = url;
    	return {
	        source: url,
	        protocol: a.protocol.replace(':',''),
	        host: getHost( a.hostname, a.port ),
			base : (function(){
				if ( a.port != 0 && a.port !== null && a.port !== "" ) return a.protocol+"//"+getHost( a.hostname, a.port )+":"+a.port;
				return a.protocol+"//"+a.host;
			})(),
	        port: a.port,
	        query: a.search,
	        params: splitQuery(a.search),
	        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
	        hash: stripH(a.hash),
	        path: (function(){
				var pn = a.pathname.replace(/^([^\/])/,'/$1');
				if (pn == '/') pn = '';
				return pn;
			})(),
	        segments: a.pathname.replace(/^\//,'').split('/'),
			hashSegments: splitHashSegments( stripH(a.hash) ),
			hashParams: splitHashParams( stripH(a.hash) )
	    };
	};

	// this is the 'active' URL object that gets returned
	
	var activeUrl = function( source )
	{	
		var sourceType = null, // elm | doc | str
			ref = null, // if it is attached to a $ object, keep the reference here
			parsed = {}; // the parsed url

		// reconstructs the hash
		var makeHash = function( prefixHash )
		{
			var hash = '';
			
			if ( parsed.hashParams != null )
			{
				// treated as query string
				hash = makeQueryString( parsed.hashParams );
			}
			else if ( parsed.hashSegments != null )
			{
				//treat as segments
				hash = makePathString( parsed.hashSegments );
			}
			
			if ( hash !== '' )
			{
				if ( parsed.hash.charAt(0) == '/' ) hash = '/'+hash;
				if ( prefixHash === true ) return '#'+hash;
		 		return hash;
			}

			return '';
		};
		
		/////////////////////////////////
	
		var updateElement = function()
		{
			if ( sourceType == 'elm' )
			{
				ref.attr( tag2attr[getTagName(ref)], parsed.source );
			}
			else if ( sourceType == 'doc' )
			{
				loc.href = parsed.source;
			}
		};
		
		var updateSource = function()
		{
			parsed.source = parsed.base+parsed.path+parsed.query;
			if ( parsed.hash && parsed.hash != '') parsed.source += '#'+parsed.hash;
		}
		
		var updateParsedAttrs = function( key, val )
		{
			switch( key )
			{
				case 'source': 
					parsed = parseUrl( val ); // need to reparse the entire URL
				break;
					
				case 'base': 
					// need to update: host, protocol, port
					if ( val.charAt(val.length-1) == '/' ) val = val.slice(0, -1); // remove the trailing slash if present
					var a = document.createElement('a');
    				a.href = parsed.base = val;
			 		parsed.protocol = a.protocol.replace(':','');
			        parsed.host = getHost( a.hostname, a.port );
			        parsed.port = a.port;
				break;
			
				case 'protocol':
				case 'host':
				case 'port':
					// need to update: base
					parsed[key] = val;
					if ( a.port != 0 && a.port !== null && a.port !== "" ) parsed.base = a.protocol+"//"+getHost( a.hostname, a.port )+":"+a.port;
					else parsed.base = a.protocol+"//"+a.host;
				break;
				
				case 'query':
					// need to update: params
					parsed.query = '?'+val.replace(/\?/,'');
					parsed.params = splitQuery( val );
				break;
				
				case 'file':
					// need to update: path, segments
					parsed.path = parsed.path.replace( new RegExp( parsed.file+'$' ), val );
					parsed.file = val;
				break;
				
				case 'hash':
					// need to update: hashParams, hashSegments
					parsed.hash = val;
					parsed.hashSegments = splitHashSegments( val );
					parsed.hashParams = splitHashParams( val );
				break;
				
				case 'path':
					// need to update: file, segments
					if ( val.charAt(0) != '/' ) val = '/'+val;
					parsed.path = val;
					parsed.file = (val.match(/\/([^\/?#]+)$/i) || [,''])[1];
				 	parsed.segments = val.replace(/^\//,'').split('/');
				break;
				
				default:
					throwParserError('you can\'t update this property directly');
				break;
			}
			
			updateSource(); // update the source
		};
		
		var updateParsedParams = function( key, val )
		{
			 // set the value, then update the query string
			parsed.params[key] = val;
			parsed.query = combineQuery( parsed.params, true );
			updateSource();
		};
	
		var updateParsedSegments = function( key, val )
		{
			 // set the value, then update the segments
			parsed.segments[key] = val;
			parsed.path = '/'+combinePath( parsed.segments );
			parsed.file = (parsed.path.match(/\/([^\/?#]+)$/i) || [,''])[1];
			updateSource();
		};
		
		var updateHashParams = function( key, val )
		{
			parsed.hashParams[key] = val;
			parsed.hash = combineQuery( parsed.hashParams, true );
			updateSource();
		};
		
		var updateHashSegments = function( key, val )
		{
			var slash = ( parsed.hash.charAt(0) == '/' ) ? '/' : '';
			parsed.hashSegments[key] = val;
			parsed.hash = slash+combinePath( parsed.hashSegments );
			updateSource();
		};
		
		var action = function( gettObj, sett, args )
		{
			if ( isGetter( args ) )
			{
				var key = args[0];
				return ( gettObj === undefined || gettObj[key] === undefined || gettObj[key] === "" ) ? null : gettObj[key];
			} 
			else if ( isSetter( args ) )
			{
				if ( isObj( args[0] ) )
				{
					for (var key in args[0]) sett( key, args[0][key] ); // set multiple properties
					if ( args[1] !== false ) updateElement(); // now update the value of the attached element
				}	
				else
				{
					sett( args[0], args[1] ); // set a single property	
					if ( args[2] !== false ) updateElement(); // now update the value of the attached element
				} 
				
				return this; // return reference to this object
			}
		};
		
		var init = function()
		{	
			if ( isObj( source ) && source.size() )
			{
				urlAttr = undefined;
				
				var tagName = getTagName(source);
				if ( tagName !== undefined ) urlAttr = tag2attr[tagName];
				
				if ( tagName !== undefined && urlAttr !== undefined )
				{
					// using a valid $ element as the source of the URL
					sourceType = 'elm';
					ref = source;
					var url = source.attr( urlAttr );
				}
				else if ( tagName !== undefined && urlAttr === undefined )
				{
					// passed a $ element, but not one that can contain a URL. throw an error.
					throwParserError('no valid URL on object');
					return;
				}
				else
				{
					// use the document location as the source
					sourceType = 'doc';
					var url = loc.href;
				
					$(document).bind('hash:change',function( hash ){
						// listen out for hashChanges, if one is triggered then update the hash
						updateParsedAttrs( 'hash', stripH( loc.hash ) );
					});
				}
			}
			else if ( ! isObj( source ) )
			{
				// just a URL string
				sourceType = 'str';
				var url = loc.href;
			}
			else
			{
				// passed an empty $ item.... don't return anything
				throwParserError( 'no valid item' );
				return;
			}
			
			parsed = parseUrl( url ); // parse the URL.

		}();
		
		return {
			
			// set/get attributes of the URL
			attr : function(){ return action( parsed, updateParsedAttrs, arguments ) },
			
			// get/set query string parameters
			param : function(){ return action( parsed.params, updateParsedParams, arguments ) },
			
			// get/set segments in the URL
			segment : function(){ return action( parsed.segments, updateParsedSegments, arguments ) },
			
			// get/set 'query string' parameters in the FRAGMENT
			hashParam : function() { return action( parsed.hashParams, updateHashParams, arguments ) },
			
			// get/set segments in the FRAGMENT
			hashSegment : function() { return action( parsed.hashSegments, updateHashSegments, arguments ) },
			
			// apply some tests
			is : function( test )
			{
				if ( test === 'internal' || test === ':internal' )
				{
					return parsed.host && parsed.host === getHost(loc.hostname);
				}
				else if ( test === 'external' || test === ':external' )
				{
					return parsed.host && parsed.host !== getHost(loc.hostname);
				}
			},
			
			// return the current URL  as a string
			toString : function(){ return parsed.source; }
		};
	
	};
	
})(jQuery);


// document ready function
$(document).ready(function() {
  
  //set some variables to make life easier
  var $panels = $("#slider_pane #window_panes .window_pane");
  var $container = $("#slider_pane #window_panes")
  var this_url = $(document).url()

  //move the panels into one long row
  $panels.css({
    'float' : 'left',
    'position' : 'relative' // so IE respects the overflow
  });
  
  //recalculate the width of the panel window
  $container.css('width',$panels[0].offsetWidth * $panels.length);
  
  //remove the scrollbars and grab the scroll object
  var $scroll = $("#slider_pane #window").css('overflow','hidden')
  
	/* Navigation */
	  // set the correct menu options
	  function nav_select() { 
	    $(this)
	      .parents("ul:first")
	        .find("li.panel_link")
	          .removeClass('selected') // remove the class from all elements
	        .end()
	      .end()
	      .parent("li.panel_link:first").addClass('selected') // add the class back to this element
	  }
	
  /**
   * within the subnav element, find the anchor tag whose href ends with  
   * the id in the url ($= is ends with) and call the nav_select function
   **/
  function trigger(url_hash) {
    var id = $(".subnav ul").find('a[href$="' + url_hash.id + '"]').get(0)
    nav_select.call(id);
  }
  
  //Bind the nav_select function to every menu option on click
  $(".subnav li.panel_link a").click(nav_select);
  

  //check the url for a specific panel, scroll to it and update the nav or just load the first panel 
  function scroll_to_id (hash) {
    $scroll.scrollTo(hash, 250);
    trigger({id : hash});
  }

  if (this_url.segment(2)) {  
    scroll_to_id ("#" + this_url.segment(2));
  }else{
    $(".subnav .panel_link:first a").click();
  }
  
  //set the offset so that the panels slide to the right spot accounting for padding if it exists
  var offset = parseInt ($container.css('paddingLeft') || 0  * -1);
  
  //set the options for the plugins
  var options = {
    target: $scroll,
    items: $panels,
    navigation: '.subnav a.panel_link',
    axis: 'x',
    onAfter: trigger,
    offset: offset,
    duration: 500,
    prev: '#back',
    next: '#forward'
  }
  
  //apply the plugins
  $("#slider_pane").serialScroll(options);
  $.localScroll(options);
  
  /**
   * if the URL has a hash, move the slider in to position, 
   * setting the duration to 1 because I don't want it to scroll in the
   * very first page load.  We don't always need this, but it ensures
   * the positioning is absolutely spot on when the pages loads.
   **/
  options.duration = 1;
  $.localScroll.hash(options);
});