Skip to content

Commit 2b45b1c

Browse files
committed
add navigation highlight
1 parent 8b4aa07 commit 2b45b1c

File tree

6 files changed

+248
-5
lines changed

6 files changed

+248
-5
lines changed

_layouts/default.html

+9
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ <h3>Links</h3>
7979
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
8080
<!-- Include all compiled plugins (below), or include individual files as needed -->
8181
<script src="js/bootstrap.min.js"></script>
82+
<script src="js/jquery.nav.js"></script>
83+
<script src="js/jquery.scrollTo.min.js"></script>
84+
<script>
85+
$(document).ready(function() {
86+
$('#nav').onePageNav({
87+
changeHash: true
88+
});
89+
});
90+
</script>
8291

8392
<script type="text/javascript">
8493
$('.collapse').collapse({

css/custom.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,11 @@ ul.subnav-list{
178178
}
179179

180180
ul.subnav-list li{
181-
padding: 0px 20px;
181+
padding: 0px 20px;
182+
}
183+
184+
#nav li.current a{
185+
font-weight: bold;
182186
}
183187

184188
.gstarted{

docs.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ <h3 id="{{ doc.id }}"> {{doc.title}} </h3>
1414
{% endfor %}
1515
</div>
1616
<div class="col-md-3 sub-nav">
17-
<ul class="subnav-list list-unstyled">
17+
<ul class="subnav-list list-unstyled" id="nav">
1818
{% for instruction in docs %}
19-
<li><a href="#{{instruction.id}}">{{instruction.title}}</a></li>
19+
<li {% if instruction.order == 1 %}class="current"{% endif %}><a href="#{{instruction.id}}">{{instruction.title}}</a></li>
2020
{% endfor %}
2121
</ul>
2222
</div>

gstarted.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ <h3 id="{{ instruction.id }}">
1616
{% endfor %}
1717
</div>
1818
<div class="col-md-3 sub-nav">
19-
<ul class="subnav-list list-unstyled">
19+
<ul class="subnav-list list-unstyled" id="nav">
2020
{% for instruction in instructions %}
21-
<li><a href="#{{instruction.id}}">{{instruction.title}}</a></li>
21+
<li {% if instruction.order == 1 %}class="current"{% endif %}><a href="#{{instruction.id}}">{{instruction.title}}</a></li>
2222
{% endfor %}
2323

2424
</ul>

js/jquery.nav.js

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
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 );

js/jquery.scrollTo.min.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)