forked from scipy-latinamerica/scipyla2017-web
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
one page navigation smooth scrolling, for better UX, once again PR: s…
- Loading branch information
Oscar Luis Garcell Martínez
committed
Oct 9, 2017
1 parent
2731c37
commit 5883354
Showing
2 changed files
with
233 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
/* | ||
* jQuery One Page Nav Plugin | ||
* http://github.com/davist11/jQuery-One-Page-Nav | ||
* | ||
* Copyright (c) 2010 Trevor Davis (http://trevordavis.net) | ||
* Dual licensed under the MIT and GPL licenses. | ||
* Uses the same license as jQuery, see: | ||
* http://jquery.org/license | ||
* | ||
* @version 3.0.0 | ||
* | ||
* Example usage: | ||
* $('#nav').onePageNav({ | ||
* currentClass: 'current', | ||
* changeHash: false, | ||
* scrollSpeed: 750 | ||
* }); | ||
*/ | ||
|
||
;(function($, window, document, undefined){ | ||
|
||
// our plugin constructor | ||
var OnePageNav = function(elem, options){ | ||
this.elem = elem; | ||
this.$elem = $(elem); | ||
this.options = options; | ||
this.metadata = this.$elem.data('plugin-options'); | ||
this.$win = $(window); | ||
this.sections = {}; | ||
this.didScroll = false; | ||
this.$doc = $(document); | ||
this.docHeight = this.$doc.height(); | ||
}; | ||
|
||
// the plugin prototype | ||
OnePageNav.prototype = { | ||
defaults: { | ||
navItems: 'a', | ||
currentClass: 'current', | ||
changeHash: false, | ||
easing: 'swing', | ||
filter: '', | ||
scrollSpeed: 750, | ||
scrollThreshold: 0.5, | ||
begin: false, | ||
end: false, | ||
scrollChange: false | ||
}, | ||
|
||
init: function() { | ||
// Introduce defaults that can be extended either | ||
// globally or using an object literal. | ||
this.config = $.extend({}, this.defaults, this.options, this.metadata); | ||
|
||
this.$nav = this.$elem.find(this.config.navItems); | ||
|
||
//Filter any links out of the nav | ||
if(this.config.filter !== '') { | ||
this.$nav = this.$nav.filter(this.config.filter); | ||
} | ||
|
||
//Handle clicks on the nav | ||
this.$nav.on('click.onePageNav', $.proxy(this.handleClick, this)); | ||
|
||
//Get the section positions | ||
this.getPositions(); | ||
|
||
//Handle scroll changes | ||
this.bindInterval(); | ||
|
||
//Update the positions on resize too | ||
this.$win.on('resize.onePageNav', $.proxy(this.getPositions, this)); | ||
|
||
return this; | ||
}, | ||
|
||
adjustNav: function(self, $parent) { | ||
self.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass); | ||
$parent.addClass(self.config.currentClass); | ||
}, | ||
|
||
bindInterval: function() { | ||
var self = this; | ||
var docHeight; | ||
|
||
self.$win.on('scroll.onePageNav', function() { | ||
self.didScroll = true; | ||
}); | ||
|
||
self.t = setInterval(function() { | ||
docHeight = self.$doc.height(); | ||
|
||
//If it was scrolled | ||
if(self.didScroll) { | ||
self.didScroll = false; | ||
self.scrollChange(); | ||
} | ||
|
||
//If the document height changes | ||
if(docHeight !== self.docHeight) { | ||
self.docHeight = docHeight; | ||
self.getPositions(); | ||
} | ||
}, 250); | ||
}, | ||
|
||
getHash: function($link) { | ||
return $link.attr('href').split('#')[1]; | ||
}, | ||
|
||
getPositions: function() { | ||
var self = this; | ||
var linkHref; | ||
var topPos; | ||
var $target; | ||
|
||
self.$nav.each(function() { | ||
linkHref = self.getHash($(this)); | ||
$target = $('#' + linkHref); | ||
|
||
if($target.length) { | ||
topPos = $target.offset().top; | ||
self.sections[linkHref] = Math.round(topPos); | ||
} | ||
}); | ||
}, | ||
|
||
getSection: function(windowPos) { | ||
var returnValue = null; | ||
var windowHeight = Math.round(this.$win.height() * this.config.scrollThreshold); | ||
|
||
for(var section in this.sections) { | ||
if((this.sections[section] - windowHeight) < windowPos) { | ||
returnValue = section; | ||
} | ||
} | ||
|
||
return returnValue; | ||
}, | ||
|
||
handleClick: function(e) { | ||
var self = this; | ||
var $link = $(e.currentTarget); | ||
var $parent = $link.parent(); | ||
var newLoc = '#' + self.getHash($link); | ||
|
||
if(!$parent.hasClass(self.config.currentClass)) { | ||
//Start callback | ||
if(self.config.begin) { | ||
self.config.begin(); | ||
} | ||
|
||
//Change the highlighted nav item | ||
self.adjustNav(self, $parent); | ||
|
||
//Removing the auto-adjust on scroll | ||
self.unbindInterval(); | ||
|
||
//Scroll to the correct position | ||
self.scrollTo(newLoc, function() { | ||
//Do we need to change the hash? | ||
if(self.config.changeHash) { | ||
window.location.hash = newLoc; | ||
} | ||
|
||
//Add the auto-adjust on scroll back in | ||
self.bindInterval(); | ||
|
||
//End callback | ||
if(self.config.end) { | ||
self.config.end(); | ||
} | ||
}); | ||
} | ||
|
||
e.preventDefault(); | ||
}, | ||
|
||
scrollChange: function() { | ||
var windowTop = this.$win.scrollTop(); | ||
var position = this.getSection(windowTop); | ||
var $parent; | ||
|
||
//If the position is set | ||
if(position !== null) { | ||
$parent = this.$elem.find('a[href$="#' + position + '"]').parent(); | ||
|
||
//If it's not already the current section | ||
if(!$parent.hasClass(this.config.currentClass)) { | ||
//Change the highlighted nav item | ||
this.adjustNav(this, $parent); | ||
|
||
//If there is a scrollChange callback | ||
if(this.config.scrollChange) { | ||
this.config.scrollChange($parent); | ||
} | ||
} | ||
} | ||
}, | ||
|
||
scrollTo: function(target, callback) { | ||
var offset = $(target).offset().top; | ||
|
||
$('html, body').animate({ | ||
scrollTop: offset | ||
}, this.config.scrollSpeed, this.config.easing, callback); | ||
}, | ||
|
||
unbindInterval: function() { | ||
clearInterval(this.t); | ||
this.$win.unbind('scroll.onePageNav'); | ||
} | ||
}; | ||
|
||
OnePageNav.defaults = OnePageNav.prototype.defaults; | ||
|
||
$.fn.onePageNav = function(options) { | ||
return this.each(function() { | ||
new OnePageNav(this, options).init(); | ||
}); | ||
}; | ||
|
||
})( jQuery, window , document ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters