;(function( $ ){
	var URI = location.href.replace(/#.*/,''); // local url without hash

	var $localScroll = $.localScroll = function( settings ){
		$('body').localScroll( settings );
	};

	// Many of these defaults, belong to jQuery.ScrollTo, check it's demo for an example of each option.
	// @see http://flesler.demos.com/jquery/scrollTo/
	// The defaults are public and can be overriden.
	$localScroll.defaults = {
		duration:1000, // How long to animate.
		axis:'y', // Which of top and left should be modified.
		event:'click', // On which event to react.
		stop:true, // Avoid queuing animations 
		target: window, // What to scroll (selector or element). The whole window by default.
		reset: true, // Used by $.localScroll.hash. If true, elements' scroll is resetted before actual scrolling
		selected: "selected", // Attribute an "selected" class when selected
		queue: true,
		hash: true,
		updatelinks: true
		/*
		lock:false, // ignore events if already animating
		lazy:false, // if true, links can be added later, and will still work.
		filter:null, // filter some anchors out of the matched elements.
		hash: false // if true, the hash of the selected link, will appear on the address bar.
		*/
	};

	// If the URL contains a hash, it will scroll to the pointed element
	$localScroll.hash = function( settings ){
		if( location.hash ){
			settings = $.extend( {}, $localScroll.defaults, settings );
			settings.hash = false; // can't be true
			
			if( settings.reset ){
				var d = settings.duration;
				delete settings.duration;
				$(settings.target).scrollTo( 0, settings );
				settings.duration = d;
			}
			scroll( 0, location, settings );
		}
	};

	$.fn.localScroll = function( settings ){	
		settings = $.extend( {}, $localScroll.defaults, settings );

		$elements = this.find('a,area')
			.filter( filter ).bind( settings.event, function(e){
				scroll( e, this, settings );
				if(settings.selected) addSelected(this);
			});
		
		$menu = $elements.end().end();
		
		if(settings.selected){
			var $selected = $elements.filter("[href="+location.hash+"]");
			if(!$selected.length) $selected = $elements.get(0);
			if(!$selected) return;
			addSelected($selected);
			addAnchor($selected, settings.target);
		}
		
		function addSelected(elem){
			var $elem = $(elem);
			var $selected = $elem.parent().parent().find('.'+settings.selected);
			$selected.removeClass(settings.selected);
			$elem.addClass(settings.selected);		
		}
		
		function addAnchor(elem, content){
			var id = $(elem).attr('href');
			$('a', content).each(function(){
				var href = $(this).attr('href');
				if(href.charAt(0) == '#' || href.indexOf('mailto') >= 0) return;
				if(href.indexOf('#') >= 0){
					href = this.href.split('#')[0];
				}
				$(this).attr('href', href+id);		
			});
		}

		return settings.lazy ?
			// use event delegation, more links can be added later.		
			this.bind( settings.event, function( e ){
				// Could use closest(), but that would leave out jQuery -1.3.x
				var a = $([e.target, e.target.parentNode]).filter(filter)[0];
				// if a valid link was clicked
				if( a )
					scroll( e, a, settings ); // do scroll.
			}) : $menu;	// bind concretely, to each matching link

		function filter(){// is this a link that points to an anchor and passes a possible filter ? href is checked to avoid a bug in FF.
			return !!this.href && !!this.hash && this.href.replace(this.hash,'') == URI && (!settings.filter || $(this).is( settings.filter ));
		};
	};

	function scroll( e, link, settings ){
		var id = link.hash.slice(1),
			elem = document.getElementById(id) || document.getElementsByName(id)[0];

		if ( !elem )
			return;

		if( e )
			e.preventDefault();

		var $target = $( settings.target );
		
		if(settings.updatelinks){
			$('a', $target).each(function(){
				var href = $(this).attr('href');
				if(href.charAt(0) == '#') return;
				
				if(this.href.indexOf('#') >= 0){
					href = this.href.split('#')[0];
				}
				$(this).attr('href', href+"#"+id);
			});
		}
	
		if( settings.lock && $target.is(':animated') ||
			settings.onBefore && settings.onBefore.call(settings, e, elem, $target) === false ) 
			return;

		if( settings.stop )
			$target.stop(true); // remove all its animations

		if( settings.hash ){
			var attr = elem.id == id ? 'id' : 'name',
				$a = $('<a> </a>').attr(attr, id).css({
					position:'absolute',
					top: $(window).scrollTop(),
					left: $(window).scrollLeft()
				});

			elem[attr] = '';
			$('body').prepend($a);
			location = link.hash;
			$a.remove();
			elem[attr] = id;
		}
			
		$target
			.scrollTo( elem, settings ) // do scroll
			.trigger('notify.serialScroll',[elem]); // notify serialScroll about this change
	};

})( jQuery );