/**
 * jQuery.LocalScroll
 * 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
 *
 * @projectDescription Animated scrolling navigation, using anchors.
 * http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html
 * @author Ariel Flesler
 * @version 1.2.7
 *
 * @id jQuery.fn.localScroll
 * @param {Object} settings Hash of settings, it is passed in to jQuery.ScrollTo, none is required.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('ul.links').localScroll();
 *
 * @example $('ul.links').localScroll({ filter:'.animated', duration:400, axis:'x' });
 *
 * @example $.localScroll({ target:'#pane', axis:'xy', queue:true, event:'mouseover' });
 *
 * Notes:
 *       - The plugin requires jQuery.ScrollTo.
 *       - The hash of settings, is passed to jQuery.ScrollTo, so the settings are valid for that plugin as well.
 *       - jQuery.localScroll can be used if the desired links, are all over the document, it accepts the same settings.
 *  - If the setting 'lazy' is set to true, then the binding will still work for later added anchors.
  *       - If onBefore returns false, the event is ignored.
 **/
;(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
              /*
              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 );

              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.
                     }) :
                     // bind concretely, to each matching link
                     this.find('a,area')
                            .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 )
                     return;

              if( e )
                     e.preventDefault();

              var $target = $( settings.target );

              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 );
