Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 espaco 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: 750,
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-62;//$('.header').outerHeight()
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;
203
                        offset = offset - 58;//$('.header').outerHeight()
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 );