;(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://www.freewebs.com/flesler/jQuery.ScrollTo/
 $localScroll.defaults = {//the defaults are public and can be overriden.
 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
 /*
 lock:false,//ignore events if already animating
 lazy:false,//if true, links can be added later, and will still work.
 target:null, //what to scroll (selector or element). Keep it null if want to scroll the whole window.
 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 ){
 settings = $.extend( {}, $localScroll.defaults, settings );
 settings.hash = false;//can't be true
 if( location.hash )
 setTimeout(function(){ scroll( 0, location, settings ); }, 0 );//better wrapped with a setTimeout
 };

 $.fn.localScroll = function( settings ){
 settings = $.extend( {}, $localScroll.defaults, settings );

 return ( settings.persistent || settings.lazy )
 ? this.bind( settings.event, function( e ){//use event delegation, more links can be added later.
 var a = $([e.target, e.target.parentNode]).filter(filter)[0];//if a valid link was clicked.
 a && scroll( e, a, settings );//do scroll.
 })
 : this.find('a')//bind concretely, to each matching link
 .filter( filter ).bind( settings.event, function(e){
 scroll( e, this, settings );
 }).end()
 .end();

 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 ){
 e && e.preventDefault();
 var $target = $( settings.target || $.scrollTo.window() );//if none specified, then the window.

 if( settings.lock && $target.is(':animated') ||
 settings.onBefore && settings.onBefore.call(link, e, elem, $target) === false ) return;

 if( settings.stop )
 $target.queue('fx',[]).stop();//remove all its animations
 $target
 .scrollTo( elem, settings )//do scroll
 .trigger('notify.serialScroll',[elem]);//notify serialScroll about this change
 if( settings.hash )
 $target.queue(function(){
 location = link.hash;
 });
 }
 };

})( jQuery );
