balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

pagenav.js (5363B)


      1 /*
      2  * jQuery One Page Nav Plugin
      3  * http://github.com/davist11/jQuery-One-Page-Nav
      4  *
      5  * Copyright (c) 2010 Trevor Davis (http://trevordavis.net)
      6  * Dual licensed under the MIT and GPL licenses.
      7  * Uses the same license as jQuery, see:
      8  * http://jquery.org/license
      9  *
     10  * @version 3.0.0
     11  *
     12  * Example usage:
     13  * $('#nav').onePageNav({
     14  *   currentClass: 'current',
     15  *   changeHash: false,
     16  *   scrollSpeed: 750
     17  * });
     18  */
     19 
     20 (function($, window, document, undefined){
     21 
     22 	// our plugin constructor
     23 	var OnePageNav = function(elem, options){
     24 		this.elem = elem;
     25 		this.$elem = $(elem);
     26 		this.options = options;
     27 		this.metadata = this.$elem.data('plugin-options');
     28 		this.$win = $(window);
     29 		this.sections = {};
     30 		this.didScroll = false;
     31 		this.$doc = $(document);
     32 		this.docHeight = this.$doc.height();
     33 	};
     34 
     35 	// the plugin prototype
     36 	OnePageNav.prototype = {
     37 		defaults: {
     38 			navItems: 'a',
     39 			currentClass: 'current',
     40 			changeHash: false,
     41 			easing: 'swing',
     42 			filter: '',
     43 			scrollSpeed: 1500,
     44 			scrollThreshold: 0.5,
     45 			begin: false,
     46 			end: false,
     47 			scrollChange: false
     48 		},
     49 
     50 		init: function() {
     51 			// Introduce defaults that can be extended either
     52 			// globally or using an object literal.
     53 			this.config = $.extend({}, this.defaults, this.options, this.metadata);
     54 
     55 			this.$nav = this.$elem.find(this.config.navItems);
     56 
     57 			//Filter any links out of the nav
     58 			if(this.config.filter !== '') {
     59 				this.$nav = this.$nav.filter(this.config.filter);
     60 			}
     61 
     62 			//Handle clicks on the nav
     63 			this.$nav.on('click.onePageNav', $.proxy(this.handleClick, this));
     64 
     65 			//Get the section positions
     66 			this.getPositions();
     67 
     68 			//Handle scroll changes
     69 			this.bindInterval();
     70 
     71 			//Update the positions on resize too
     72 			this.$win.on('resize.onePageNav', $.proxy(this.getPositions, this));
     73 
     74 			return this;
     75 		},
     76 
     77 		adjustNav: function(self, $parent) {
     78 			self.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass);
     79 			$parent.addClass(self.config.currentClass);
     80 		},
     81 
     82 		bindInterval: function() {
     83 			var self = this;
     84 			var docHeight;
     85 
     86 			self.$win.on('scroll.onePageNav', function() {
     87 				self.didScroll = true;
     88 			});
     89 
     90 			self.t = setInterval(function() {
     91 				docHeight = self.$doc.height();
     92 
     93 				//If it was scrolled
     94 				if(self.didScroll) {
     95 					self.didScroll = false;
     96 					self.scrollChange();
     97 				}
     98 
     99 				//If the document height changes
    100 				if(docHeight !== self.docHeight) {
    101 					self.docHeight = docHeight;
    102 					self.getPositions();
    103 				}
    104 			}, 250);
    105 		},
    106 
    107 		getHash: function($link) {
    108 			return $link.attr('href').split('#')[1];
    109 		},
    110 
    111 		getPositions: function() {
    112 			var self = this;
    113 			var linkHref;
    114 			var topPos;
    115 			var $target;
    116 
    117 			self.$nav.each(function() {
    118 				linkHref = self.getHash($(this));
    119 				$target = $('#' + linkHref);
    120 
    121 				if($target.length) {
    122 					topPos = $target.offset().top;
    123 					self.sections[linkHref] = Math.round(topPos);
    124 				}
    125 			});
    126 		},
    127 
    128 		getSection: function(windowPos) {
    129 			var returnValue = null;
    130 			var windowHeight = Math.round(this.$win.height() * this.config.scrollThreshold);
    131 
    132 			for(var section in this.sections) {
    133 				if((this.sections[section] - windowHeight) < windowPos) {
    134 					returnValue = section;
    135 				}
    136 			}
    137 
    138 			return returnValue;
    139 		},
    140 
    141 		handleClick: function(e) {
    142 			var self = this;
    143 			var $link = $(e.currentTarget);
    144 			var $parent = $link.parent();
    145 			var newLoc = '#' + self.getHash($link);
    146 
    147 			if(!$parent.hasClass(self.config.currentClass)) {
    148 				//Start callback
    149 				if(self.config.begin) {
    150 					self.config.begin();
    151 				}
    152 
    153 				//Change the highlighted nav item
    154 				self.adjustNav(self, $parent);
    155 
    156 				//Removing the auto-adjust on scroll
    157 				self.unbindInterval();
    158 
    159 				//Scroll to the correct position
    160 				self.scrollTo(newLoc, function() {
    161 					//Do we need to change the hash?
    162 					if(self.config.changeHash) {
    163 						window.location.hash = newLoc;
    164 					}
    165 
    166 					//Add the auto-adjust on scroll back in
    167 					self.bindInterval();
    168 
    169 					//End callback
    170 					if(self.config.end) {
    171 						self.config.end();
    172 					}
    173 				});
    174 			}
    175 
    176 			e.preventDefault();
    177 		},
    178 
    179 		scrollChange: function() {
    180 			var windowTop = this.$win.scrollTop();
    181 			var position = this.getSection(windowTop);
    182 			var $parent;
    183 
    184 			//If the position is set
    185 			if(position !== null) {
    186 				$parent = this.$elem.find('a[href$="#' + position + '"]').parent();
    187 
    188 				//If it's not already the current section
    189 				if(!$parent.hasClass(this.config.currentClass)) {
    190 					//Change the highlighted nav item
    191 					this.adjustNav(this, $parent);
    192 
    193 					//If there is a scrollChange callback
    194 					if(this.config.scrollChange) {
    195 						this.config.scrollChange($parent);
    196 					}
    197 				}
    198 			}
    199 		},
    200 
    201 		scrollTo: function(target, callback) {
    202 			var offset = $(target).offset().top-70;
    203 
    204 			$('html, body').animate({
    205 				scrollTop: offset
    206 			}, this.config.scrollSpeed, this.config.easing, callback);
    207 		},
    208 
    209 		unbindInterval: function() {
    210 			clearInterval(this.t);
    211 			this.$win.unbind('scroll.onePageNav');
    212 		}
    213 	};
    214 
    215 	OnePageNav.defaults = OnePageNav.prototype.defaults;
    216 
    217 	$.fn.onePageNav = function(options) {
    218 		return this.each(function() {
    219 			new OnePageNav(this, options).init();
    220 		});
    221 	};
    222 
    223 })( jQuery, window , document );