Difference between revisions of "Team:SCU China/jquerynav"
(Created page with "/* * 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...") |
|||
Line 3: | Line 3: | ||
* http://github.com/davist11/jQuery-One-Page-Nav | * http://github.com/davist11/jQuery-One-Page-Nav | ||
* | * | ||
− | * | + | * Copyright (c) 2010 Trevor Davis (http://trevordavis.net) |
− | + | * Dual licensed under the MIT and GPL licenses. | |
− | Copyright (c) 2010 Trevor Davis (http://trevordavis.net) | + | |
− | * Dual licensed under the MIT and | + | |
− | + | ||
− | GPL licenses. | + | |
* Uses the same license as jQuery, see: | * Uses the same license as jQuery, see: | ||
* http://jquery.org/license | * http://jquery.org/license | ||
* | * | ||
− | * | + | * @version 3.0.0 |
− | + | ||
− | @version 3.0.0 | + | |
* | * | ||
* Example usage: | * Example usage: | ||
* $('#nav').onePageNav({ | * $('#nav').onePageNav({ | ||
* currentClass: 'current', | * currentClass: 'current', | ||
− | * | + | * changeHash: false, |
− | + | ||
− | changeHash: false, | + | |
* scrollSpeed: 750 | * scrollSpeed: 750 | ||
* }); | * }); | ||
Line 28: | Line 20: | ||
;(function($, window, document, undefined){ | ;(function($, window, document, undefined){ | ||
− | + | // our plugin constructor | |
− | + | ||
− | // our plugin constructor | + | |
var OnePageNav = function(elem, options){ | var OnePageNav = function(elem, options){ | ||
− | + | this.elem = elem; | |
− | + | ||
− | this.elem = elem; | + | |
this.$elem = $(elem); | this.$elem = $(elem); | ||
this.options = options; | this.options = options; | ||
− | + | this.metadata = this.$elem.data('plugin-options'); | |
− | + | ||
− | this.metadata = this.$elem.data('plugin-options'); | + | |
this.$win = $(window); | this.$win = $(window); | ||
− | + | this.sections = {}; | |
− | + | ||
− | this.sections = {}; | + | |
this.didScroll = false; | this.didScroll = false; | ||
this.$doc = $(document); | this.$doc = $(document); | ||
− | + | this.docHeight = this.$doc.height(); | |
− | + | ||
− | + | ||
}; | }; | ||
// the plugin prototype | // the plugin prototype | ||
− | + | OnePageNav.prototype = { | |
− | + | ||
− | OnePageNav.prototype = { | + | |
defaults: { | defaults: { | ||
navItems: 'a', | navItems: 'a', | ||
− | + | currentClass: 'current', | |
− | + | ||
− | + | ||
changeHash: false, | changeHash: false, | ||
− | + | easing: 'swing', | |
− | + | ||
− | easing: 'swing', | + | |
filter: '', | filter: '', | ||
scrollSpeed: 750, | scrollSpeed: 750, | ||
− | + | scrollThreshold: 0.5, | |
− | + | ||
− | + | ||
begin: false, | begin: false, | ||
− | end: | + | end: false, |
− | + | ||
− | false, | + | |
scrollChange: false | scrollChange: false | ||
}, | }, | ||
init: function() { | init: function() { | ||
− | + | // Introduce defaults that can be extended either | |
− | + | // globally or using an object literal. | |
− | + | this.config = $.extend({}, this.defaults, this.options, this.metadata); | |
− | // | + | |
− | + | ||
− | globally or using an object literal. | + | |
− | this.config = $.extend({}, | + | |
− | + | ||
− | this.defaults, this.options, this.metadata); | + | |
− | + | ||
− | + | ||
− | (this.config.navItems); | + | this.$nav = this.$elem.find(this.config.navItems); |
//Filter any links out of the nav | //Filter any links out of the nav | ||
− | + | if(this.config.filter !== '') { | |
− | + | this.$nav = this.$nav.filter(this.config.filter); | |
− | if(this.config.filter !== '') { | + | |
− | this.$nav = this.$nav.filter | + | |
− | + | ||
− | (this.config.filter); | + | |
} | } | ||
//Handle clicks on the nav | //Handle clicks on the nav | ||
− | + | this.$nav.on('click.onePageNav', $.proxy(this.handleClick, this)); | |
− | + | //Get the section positions | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
this.getPositions(); | this.getPositions(); | ||
− | + | //Handle scroll changes | |
− | + | ||
− | //Handle scroll changes | + | |
this.bindInterval(); | this.bindInterval(); | ||
− | //Update the | + | //Update the positions on resize too |
− | + | this.$win.on('resize.onePageNav', $.proxy(this.getPositions, this)); | |
− | positions on resize too | + | |
− | this.$win.on('resize.onePageNav', $.proxy | + | |
− | + | ||
− | (this.getPositions, this)); | + | |
return this; | return this; | ||
}, | }, | ||
− | + | adjustNav: function(self, $parent) { | |
− | + | self.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass); | |
− | adjustNav: function(self, $parent) { | + | $parent.addClass(self.config.currentClass); |
− | self.$elem.find('.' + | + | |
− | + | ||
− | self.config.currentClass).removeClass(self.config.currentClass); | + | |
− | + | ||
− | + | ||
− | $parent.addClass(self.config.currentClass); | + | |
}, | }, | ||
− | bindInterval: | + | bindInterval: function() { |
− | + | ||
− | function() { | + | |
var self = this; | var self = this; | ||
var docHeight; | var docHeight; | ||
− | + | self.$win.on('scroll.onePageNav', function() { | |
− | + | self.didScroll = true; | |
− | + | ||
− | + | ||
− | + | ||
− | self.didScroll = true; | + | |
}); | }); | ||
− | self.t = setInterval | + | self.t = setInterval(function() { |
− | + | ||
− | (function() { | + | |
docHeight = self.$doc.height(); | docHeight = self.$doc.height(); | ||
− | + | //If it was scrolled | |
− | + | ||
− | //If it was scrolled | + | |
if(self.didScroll) { | if(self.didScroll) { | ||
− | + | self.didScroll = false; | |
− | + | ||
− | + | ||
self.scrollChange(); | self.scrollChange(); | ||
− | + | } | |
− | + | ||
− | + | ||
//If the document height changes | //If the document height changes | ||
− | + | if(docHeight !== self.docHeight) { | |
− | + | self.docHeight = docHeight; | |
− | + | ||
− | + | ||
− | + | ||
− | self.docHeight = docHeight; | + | |
self.getPositions(); | self.getPositions(); | ||
− | + | } | |
− | + | ||
− | + | ||
}, 250); | }, 250); | ||
}, | }, | ||
− | getHash: | + | getHash: function($link) { |
− | + | ||
− | function($link) { | + | |
return $link.attr('href').split('#')[1]; | return $link.attr('href').split('#')[1]; | ||
− | + | }, | |
− | + | ||
− | }, | + | |
getPositions: function() { | getPositions: function() { | ||
var self = this; | var self = this; | ||
− | + | var linkHref; | |
− | + | ||
− | + | ||
var topPos; | var topPos; | ||
var $target; | var $target; | ||
− | + | self.$nav.each(function() { | |
− | + | linkHref = self.getHash($(this)); | |
− | + | ||
− | linkHref = self.getHash | + | |
− | + | ||
− | ($(this)); | + | |
$target = $('#' + linkHref); | $target = $('#' + linkHref); | ||
− | + | if($target.length) { | |
− | + | ||
− | if($target.length) { | + | |
topPos = $target.offset().top; | topPos = $target.offset().top; | ||
− | + | self.sections[linkHref] = Math.round(topPos); | |
− | + | } | |
− | + | ||
− | + | ||
− | + | ||
− | } | + | |
}); | }); | ||
}, | }, | ||
getSection: function(windowPos) { | 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) { | |
− | + | ||
− | + | ||
− | + | ||
− | for(var section in | + | |
− | + | ||
− | this.sections) { | + | |
− | if((this.sections[section] - windowHeight) < | + | |
− | + | ||
− | windowPos) { | + | |
returnValue = section; | returnValue = section; | ||
− | + | } | |
− | + | ||
− | } | + | |
} | } | ||
Line 241: | Line 139: | ||
}, | }, | ||
− | + | handleClick: function(e) { | |
− | + | ||
− | handleClick: function(e) { | + | |
var self = this; | var self = this; | ||
− | var | + | var $link = $(e.currentTarget); |
− | + | ||
− | $link = $(e.currentTarget); | + | |
var $parent = $link.parent(); | var $parent = $link.parent(); | ||
− | + | var newLoc = '#' + self.getHash($link); | |
− | + | if(!$parent.hasClass(self.config.currentClass)) { | |
− | + | ||
− | if(!$parent.hasClass | + | |
− | + | ||
− | (self.config.currentClass)) { | + | |
//Start callback | //Start callback | ||
− | + | if(self.config.begin) { | |
− | + | ||
− | + | ||
self.config.begin(); | self.config.begin(); | ||
− | + | } | |
− | + | ||
− | + | ||
//Change the highlighted nav item | //Change the highlighted nav item | ||
− | + | self.adjustNav(self, $parent); | |
− | + | //Removing the auto-adjust on scroll | |
− | + | ||
− | //Removing the | + | |
− | + | ||
− | auto-adjust on scroll | + | |
self.unbindInterval(); | self.unbindInterval(); | ||
− | + | //Scroll to the correct position | |
− | + | self.scrollTo(newLoc, function() { | |
− | //Scroll to the correct position | + | |
− | self.scrollTo(newLoc, | + | |
− | + | ||
− | function() { | + | |
//Do we need to change the hash? | //Do we need to change the hash? | ||
− | + | if(self.config.changeHash) { | |
− | + | window.location.hash = newLoc; | |
− | + | ||
− | + | ||
− | + | ||
− | window.location.hash = newLoc; | + | |
} | } | ||
− | + | //Add the auto-adjust on scroll back in | |
− | + | self.bindInterval(); | |
− | + | ||
− | + | ||
− | + | ||
− | self.bindInterval(); | + | |
//End callback | //End callback | ||
− | + | if(self.config.end) { | |
− | + | ||
− | + | ||
self.config.end(); | self.config.end(); | ||
− | + | } | |
− | + | ||
− | + | ||
}); | }); | ||
} | } | ||
− | + | e.preventDefault(); | |
− | + | ||
− | + | ||
}, | }, | ||
scrollChange: function() { | scrollChange: function() { | ||
− | + | var windowTop = this.$win.scrollTop(); | |
− | + | var position = this.getSection(windowTop); | |
− | + | ||
− | var position = | + | |
− | + | ||
− | this.getSection(windowTop); | + | |
var $parent; | var $parent; | ||
− | //If the | + | //If the position is set |
− | + | ||
− | position is set | + | |
if(position !== null) { | if(position !== null) { | ||
− | $parent = | + | $parent = this.$elem.find('a[href$="#' + position + '"]').parent(); |
− | + | //If it's not already the current section | |
− | + | if(!$parent.hasClass(this.config.currentClass)) { | |
− | //If | + | //Change the highlighted nav item |
− | + | ||
− | it's not already the current section | + | |
− | if(!$parent.hasClass | + | |
− | + | ||
− | (this.config.currentClass)) { | + | |
− | //Change the highlighted nav | + | |
− | + | ||
− | item | + | |
this.adjustNav(this, $parent); | this.adjustNav(this, $parent); | ||
− | + | //If there is a scrollChange callback | |
− | + | if(this.config.scrollChange) { | |
− | + | this.config.scrollChange($parent); | |
− | if | + | |
− | + | ||
− | (this.config.scrollChange) { | + | |
− | + | ||
− | + | ||
− | this.config.scrollChange($parent); | + | |
} | } | ||
− | + | } | |
− | + | ||
− | + | ||
} | } | ||
}, | }, | ||
− | scrollTo: function(target, | + | scrollTo: function(target, callback) { |
− | + | ||
− | callback) { | + | |
var offset = $(target).offset().top; | var offset = $(target).offset().top; | ||
− | + | $('html, body').animate({ | |
− | + | ||
− | $('html, body').animate({ | + | |
scrollTop: offset | scrollTop: offset | ||
− | + | }, this.config.scrollSpeed, this.config.easing, callback); | |
− | + | ||
− | }, this.config.scrollSpeed, this.config.easing, callback); | + | |
}, | }, | ||
− | + | unbindInterval: function() { | |
− | + | ||
− | unbindInterval: function() { | + | |
clearInterval(this.t); | clearInterval(this.t); | ||
− | + | this.$win.unbind('scroll.onePageNav'); | |
− | + | ||
− | this.$win.unbind('scroll.onePageNav'); | + | |
} | } | ||
}; | }; | ||
− | OnePageNav.defaults = | + | OnePageNav.defaults = OnePageNav.prototype.defaults; |
− | + | ||
− | OnePageNav.prototype.defaults; | + | |
$.fn.onePageNav = function(options) { | $.fn.onePageNav = function(options) { | ||
− | return | + | return this.each(function() { |
− | + | ||
− | this.each(function() { | + | |
new OnePageNav(this, options).init(); | new OnePageNav(this, options).init(); | ||
}); | }); | ||
− | + | }; | |
− | + | ||
− | }; | + | |
})( jQuery, window , document ); | })( jQuery, window , document ); |
Latest revision as of 21:44, 16 September 2015
/*
* 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 );