|
|
- /**
- * Single Page Nav Plugin
- * Copyright (c) 2014 Chris Wojcik <hello@chriswojcik.net>
- * Dual licensed under MIT and GPL.
- * @author Chris Wojcik
- * @version 1.2.0
- */
-
- // Utility
- if (typeof Object.create !== 'function') {
- Object.create = function(obj) {
- function F() {}
- F.prototype = obj;
- return new F();
- };
- }
-
- (function($, window, document, undefined) {
- "use strict";
-
- var SinglePageNav = {
-
- init: function(options, container) {
-
- this.options = $.extend({}, $.fn.singlePageNav.defaults, options);
-
- this.container = container;
- this.$container = $(container);
- this.$links = this.$container.find('a');
-
- if (this.options.filter !== '') {
- this.$links = this.$links.filter(this.options.filter);
- }
-
- this.$window = $(window);
- this.$htmlbody = $('html, body');
-
- this.$links.on('click.singlePageNav', $.proxy(this.handleClick, this));
-
- this.didScroll = false;
- this.checkPosition();
- this.setTimer();
- },
-
- handleClick: function(e) {
- var self = this,
- link = e.currentTarget,
- $elem = $(link.hash);
-
- e.preventDefault();
-
- if ($elem.length) { // Make sure the target elem exists
-
- // Prevent active link from cycling during the scroll
- self.clearTimer();
-
- // Before scrolling starts
- if (typeof self.options.beforeStart === 'function') {
- self.options.beforeStart();
- }
-
- self.setActiveLink(link.hash);
-
- self.scrollTo($elem, function() {
-
- if (self.options.updateHash && history.pushState) {
- history.pushState(null,null, link.hash);
- }
-
- self.setTimer();
-
- // After scrolling ends
- if (typeof self.options.onComplete === 'function') {
- self.options.onComplete();
- }
- });
- }
- },
-
- scrollTo: function($elem, callback) {
- var self = this;
- var target = self.getCoords($elem).top;
- var called = false;
-
- self.$htmlbody.stop().animate(
- {scrollTop: target},
- {
- duration: self.options.speed,
- easing: self.options.easing,
- complete: function() {
- if (typeof callback === 'function' && !called) {
- callback();
- }
- called = true;
- }
- }
- );
- },
-
- setTimer: function() {
- var self = this;
-
- self.$window.on('scroll.singlePageNav', function() {
- self.didScroll = true;
- });
-
- self.timer = setInterval(function() {
- if (self.didScroll) {
- self.didScroll = false;
- self.checkPosition();
- }
- }, 250);
- },
-
- clearTimer: function() {
- clearInterval(this.timer);
- this.$window.off('scroll.singlePageNav');
- this.didScroll = false;
- },
-
- // Check the scroll position and set the active section
- checkPosition: function() {
- var scrollPos = this.$window.scrollTop();
- var currentSection = this.getCurrentSection(scrollPos);
- if(currentSection!==null) {
- this.setActiveLink(currentSection);
- }
- },
-
- getCoords: function($elem) {
- return {
- top: Math.round($elem.offset().top) - this.options.offset
- };
- },
-
- setActiveLink: function(href) {
- var $activeLink = this.$container.find("a[href$='" + href + "']");
-
- if (!$activeLink.hasClass(this.options.currentClass)) {
- this.$links.removeClass(this.options.currentClass);
- $activeLink.addClass(this.options.currentClass);
- }
- },
-
- getCurrentSection: function(scrollPos) {
- var i, hash, coords, section;
-
- for (i = 0; i < this.$links.length; i++) {
- hash = this.$links[i].hash;
-
- if ($(hash).length) {
- coords = this.getCoords($(hash));
-
- if (scrollPos >= coords.top - this.options.threshold) {
- section = hash;
- }
- }
- }
-
- // The current section or the first link if it is found
- return section || ((this.$links.length===0) ? (null) : (this.$links[0].hash));
- }
- };
-
- $.fn.singlePageNav = function(options) {
- return this.each(function() {
- var singlePageNav = Object.create(SinglePageNav);
- singlePageNav.init(options, this);
- });
- };
-
- $.fn.singlePageNav.defaults = {
- offset: 0,
- threshold: 120,
- speed: 400,
- currentClass: 'current',
- easing: 'swing',
- updateHash: false,
- filter: '',
- onComplete: false,
- beforeStart: false
- };
-
- })(jQuery, window, document);
|