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 navHeight: 75, 44 scrollSpeed: 750, 45 scrollThreshold: 0.5, 46 begin: false, 47 end: false, 48 scrollChange: false 49 }, 50 51 init: function () { 52 // Introduce defaults that can be extended either 53 // globally or using an object literal. 54 this.config = $.extend({}, this.defaults, this.options, this.metadata); 55 56 this.$nav = this.$elem.find(this.config.navItems); 57 58 //Filter any links out of the nav 59 if (this.config.filter !== '') { 60 this.$nav = this.$nav.filter(this.config.filter); 61 } 62 63 //Handle clicks on the nav 64 this.$nav.on('click.onePageNav', $.proxy(this.handleClick, this)); 65 66 //Get the section positions 67 this.getPositions(); 68 69 //Handle scroll changes 70 this.bindInterval(); 71 72 //Update the positions on resize too 73 this.$win.on('resize.onePageNav', $.proxy(this.getPositions, this)); 74 75 return this; 76 }, 77 78 adjustNav: function (self, $parent) { 79 self.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass); 80 $parent.addClass(self.config.currentClass); 81 }, 82 83 bindInterval: function () { 84 var self = this; 85 var docHeight; 86 87 self.$win.on('scroll.onePageNav', function () { 88 self.didScroll = true; 89 }); 90 91 self.t = setInterval(function () { 92 docHeight = self.$doc.height(); 93 94 //If it was scrolled 95 if (self.didScroll) { 96 self.didScroll = false; 97 self.scrollChange(); 98 } 99 100 //If the document height changes 101 if (docHeight !== self.docHeight) { 102 self.docHeight = docHeight; 103 self.getPositions(); 104 } 105 }, 250); 106 }, 107 108 getHash: function ($link) { 109 return $link.attr('href').split('#')[1]; 110 }, 111 112 getPositions: function () { 113 var self = this; 114 var linkHref; 115 var topPos; 116 var $target; 117 118 self.$nav.each(function () { 119 linkHref = self.getHash($(this)); 120 $target = $('#' + linkHref); 121 122 if ($target.length) { 123 topPos = $target.offset().top; 124 125 self.sections[linkHref] = Math.round(topPos); 126 } 127 }); 128 }, 129 130 getSection: function (windowPos) { 131 var returnValue = null; 132 var windowHeight = Math.round(this.$win.height() * this.config.scrollThreshold); 133 134 135 for (var section in this.sections) { 136 if ((this.sections[section] - windowHeight) < windowPos) { 137 returnValue = section; 138 139 } 140 } 141 142 return returnValue; 143 }, 144 145 handleClick: function (e) { 146 var self = this; 147 var $link = $(e.currentTarget); 148 var $parent = $link.parent(); 149 var newLoc = '#' + self.getHash($link); 150 151 if (!$parent.hasClass(self.config.currentClass)) { 152 //Start callback 153 if (self.config.begin) { 154 self.config.begin(); 155 } 156 157 //Change the highlighted nav item 158 self.adjustNav(self, $parent); 159 160 //Removing the auto-adjust on scroll 161 self.unbindInterval(); 162 163 //Scroll to the correct position 164 self.scrollTo(newLoc, function () { 165 //Do we need to change the hash? 166 if (self.config.changeHash) { 167 window.location.hash = newLoc; 168 } 169// $('#aboutUs').offset({'top':'60'}); 170 //Add the auto-adjust on scroll back in 171 self.bindInterval(); 172 173 //End callback 174 if (self.config.end) { 175 self.config.end(); 176 } 177 }); 178 } 179 180 e.preventDefault(); 181 }, 182 183 scrollChange: function () { 184 var windowTop = this.$win.scrollTop();
185 var position = this.getSection(windowTop); 186 var $parent; 187 188 //If the position is set 189 if (position !== null) { 190 $parent = this.$elem.find('a[href$="#' + position + '"]').parent(); 191 192 //If it's not already the current section 193 if (!$parent.hasClass(this.config.currentClass)) { 194 //Change the highlighted nav item 195 this.adjustNav(this, $parent); 196 197 //If there is a scrollChange callback 198 if (this.config.scrollChange) { 199 this.config.scrollChange($parent); 200 } 201 } 202 } 203 }, 204 205 scrollTo: function (target, callback) { 206 var offset = $(target).offset().top - this.config.navHeight; 207 $('html, body').animate({ 208 scrollTop: offset 209 }, this.config.scrollSpeed, this.config.easing, callback); 210 }, 211 212 unbindInterval: function () { 213 clearInterval(this.t); 214 this.$win.unbind('scroll.onePageNav'); 215 } 216 }; 217 218 OnePageNav.defaults = OnePageNav.prototype.defaults; 219 220 $.fn.onePageNav = function (options) { 221 return this.each(function () { 222 new OnePageNav(this, options).init(); 223 }); 224 }; 225 226})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.