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 ;
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
+
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 ) ;
0 commit comments