Skip to content

Commit 763c593

Browse files
authored
Merge pull request mmistakes#2020 from edemaine/scrollspy
2 parents 47eb693 + 8737711 commit 763c593

File tree

7 files changed

+309
-18
lines changed

7 files changed

+309
-18
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ To test the theme, run `bundle exec rake preview` and open your browser at `http
186186
- [FitVids.JS](http://fitvidsjs.com/)
187187
- [GreedyNav.js](https://github.com/lukejacksonn/GreedyNav)
188188
- [jQuery Smooth Scroll](https://github.com/kswedberg/jquery-smooth-scroll)
189+
- [jQuery throttle / debounce](http://benalman.com/projects/jquery-throttle-debounce-plugin/)
189190
- [Lunr](http://lunrjs.com)
190191

191192
---
@@ -244,6 +245,10 @@ Minimal Mistakes incorporates [jQuery Smooth Scroll](https://github.com/kswedber
244245
Copyright (c) 2017 Karl Swedberg.
245246
jQuery Smooth Scroll is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
246247

248+
Minimal Mistakes incorporates [jQuery throttle / debounce](http://benalman.com/projects/jquery-throttle-debounce-plugin/),
249+
Copyright (c) 2010 "Cowboy" Ben Alman.
250+
jQuery throttle / debounce is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
251+
247252
Minimal Mistakes incorporates [GreedyNav.js](https://github.com/lukejacksonn/GreedyNav),
248253
Copyright (c) 2015 Luke Jackson.
249254
GreedyNav.js is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).

_sass/minimal-mistakes/_navigation.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,11 @@
507507
border-top-left-radius: $border-radius;
508508
border-top-right-radius: $border-radius;
509509
}
510+
511+
// Scrollspy marks toc items as .active when they are in focus
512+
.active {
513+
@include yiq-contrasted($active-color);
514+
}
510515
}
511516

512517
.toc__menu {

_sass/minimal-mistakes/_variables.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ $warning-color: #d67f05 !default;
6868
$danger-color: #ee5f5b !default;
6969
$info-color: #3b9cba !default;
7070
$focus-color: $primary-color !default;
71+
$active-color: mix(#fff, $primary-color, 80%) !default;
7172

7273
/* YIQ color contrast */
7374
$yiq-contrasted-dark-default: $dark-gray !default;

assets/js/_main.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,12 @@ $(document).ready(function() {
66
// Sticky footer
77
var bumpIt = function() {
88
$("body").css("margin-bottom", $(".page__footer").outerHeight(true));
9-
},
10-
didResize = false;
9+
};
1110

1211
bumpIt();
13-
14-
$(window).resize(function() {
15-
didResize = true;
16-
});
17-
setInterval(function() {
18-
if (didResize) {
19-
didResize = false;
20-
bumpIt();
21-
}
22-
}, 250);
12+
$(window).resize(jQuery.throttle(250, function() {
13+
bumpIt();
14+
}));
2315

2416
// FitVids init
2517
$("#main").fitVids();
@@ -64,10 +56,13 @@ $(document).ready(function() {
6456
// Smooth scrolling
6557

6658
// Bind popstate event listener to support back/forward buttons.
59+
var smoothScrolling = false;
6760
$(window).bind("popstate", function (event) {
6861
$.smoothScroll({
6962
scrollTarget: location.hash,
70-
offset: -20
63+
offset: -20,
64+
beforeScroll: function() { smoothScrolling = true; },
65+
afterScroll: function() { smoothScrolling = false; }
7166
});
7267
});
7368
// Override clicking on links to smooth scroll
@@ -83,6 +78,39 @@ $(document).ready(function() {
8378
$(window).trigger("popstate");
8479
}
8580

81+
// Scrollspy equivalent: update hash fragment while scrolling.
82+
$(window).scroll(jQuery.throttle(250, function() {
83+
// Don't run while smooth scrolling (from clicking on a link).
84+
if (smoothScrolling) return;
85+
var scrollTop = $(window).scrollTop() + 20; // 20 = offset
86+
var links = [];
87+
$("nav.toc a").each(function() {
88+
var link = $(this);
89+
var href = link.attr("href");
90+
if (href && href[0] == "#") {
91+
var element = $(href);
92+
links.push({
93+
link: link,
94+
href: href,
95+
top: element.offset().top
96+
});
97+
link.removeClass('active');
98+
}
99+
});
100+
for (var i = 0; i < links.length; i++) {
101+
var top = links[i].top;
102+
var bottom = (i < links.length - 1 ? links[i+1].top : Infinity);
103+
if (top <= scrollTop && scrollTop < bottom) {
104+
// Mark all ancestors as active
105+
links[i].link.parents("li").children("a").addClass('active');
106+
if (links[i].href !== location.hash) {
107+
history.replaceState(null, null, links[i].href);
108+
}
109+
break;
110+
}
111+
}
112+
}));
113+
86114
// add lightbox class to all image links
87115
$(
88116
"a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif']"

assets/js/main.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/*!
2+
* jQuery throttle / debounce - v1.1 - 3/7/2010
3+
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
4+
*
5+
* Copyright (c) 2010 "Cowboy" Ben Alman
6+
* Dual licensed under the MIT and GPL licenses.
7+
* http://benalman.com/about/license/
8+
*/
9+
10+
// Script: jQuery throttle / debounce: Sometimes, less is more!
11+
//
12+
// *Version: 1.1, Last updated: 3/7/2010*
13+
//
14+
// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
15+
// GitHub - http://github.com/cowboy/jquery-throttle-debounce/
16+
// Source - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
17+
// (Minified) - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
18+
//
19+
// About: License
20+
//
21+
// Copyright (c) 2010 "Cowboy" Ben Alman,
22+
// Dual licensed under the MIT and GPL licenses.
23+
// http://benalman.com/about/license/
24+
//
25+
// About: Examples
26+
//
27+
// These working examples, complete with fully commented code, illustrate a few
28+
// ways in which this plugin can be used.
29+
//
30+
// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
31+
// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
32+
//
33+
// About: Support and Testing
34+
//
35+
// Information about what version or versions of jQuery this plugin has been
36+
// tested with, what browsers it has been tested in, and where the unit tests
37+
// reside (so you can test it yourself).
38+
//
39+
// jQuery Versions - none, 1.3.2, 1.4.2
40+
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
41+
// Unit Tests - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
42+
//
43+
// About: Release History
44+
//
45+
// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
46+
// executed later than they should. Reworked a fair amount of internal
47+
// logic as well.
48+
// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
49+
// from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
50+
// no_trailing throttle parameter and debounce functionality.
51+
//
52+
// Topic: Note for non-jQuery users
53+
//
54+
// jQuery isn't actually required for this plugin, because nothing internal
55+
// uses any jQuery methods or properties. jQuery is just used as a namespace
56+
// under which these methods can exist.
57+
//
58+
// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
59+
// when this plugin is loaded, the method described below will be created in
60+
// the `Cowboy` namespace. Usage will be exactly the same, but instead of
61+
// $.method() or jQuery.method(), you'll need to use Cowboy.method().
62+
63+
(function(window,undefined){
64+
'$:nomunge'; // Used by YUI compressor.
65+
66+
// Since jQuery really isn't required for this plugin, use `jQuery` as the
67+
// namespace only if it already exists, otherwise use the `Cowboy` namespace,
68+
// creating it if necessary.
69+
var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
70+
71+
// Internal method reference.
72+
jq_throttle;
73+
74+
// Method: jQuery.throttle
75+
//
76+
// Throttle execution of a function. Especially useful for rate limiting
77+
// execution of handlers on events like resize and scroll. If you want to
78+
// rate-limit execution of a function to a single time, see the
79+
// <jQuery.debounce> method.
80+
//
81+
// In this visualization, | is a throttled-function call and X is the actual
82+
// callback execution:
83+
//
84+
// > Throttled with `no_trailing` specified as false or unspecified:
85+
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
86+
// > X X X X X X X X X X X X
87+
// >
88+
// > Throttled with `no_trailing` specified as true:
89+
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
90+
// > X X X X X X X X X X
91+
//
92+
// Usage:
93+
//
94+
// > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
95+
// >
96+
// > jQuery('selector').bind( 'someevent', throttled );
97+
// > jQuery('selector').unbind( 'someevent', throttled );
98+
//
99+
// This also works in jQuery 1.4+:
100+
//
101+
// > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
102+
// > jQuery('selector').unbind( 'someevent', callback );
103+
//
104+
// Arguments:
105+
//
106+
// delay - (Number) A zero-or-greater delay in milliseconds. For event
107+
// callbacks, values around 100 or 250 (or even higher) are most useful.
108+
// no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
109+
// true, callback will only execute every `delay` milliseconds while the
110+
// throttled-function is being called. If no_trailing is false or
111+
// unspecified, callback will be executed one final time after the last
112+
// throttled-function call. (After the throttled-function has not been
113+
// called for `delay` milliseconds, the internal counter is reset)
114+
// callback - (Function) A function to be executed after delay milliseconds.
115+
// The `this` context and all arguments are passed through, as-is, to
116+
// `callback` when the throttled-function is executed.
117+
//
118+
// Returns:
119+
//
120+
// (Function) A new, throttled, function.
121+
122+
$.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
123+
// After wrapper has stopped being called, this timeout ensures that
124+
// `callback` is executed at the proper times in `throttle` and `end`
125+
// debounce modes.
126+
var timeout_id,
127+
128+
// Keep track of the last time `callback` was executed.
129+
last_exec = 0;
130+
131+
// `no_trailing` defaults to falsy.
132+
if ( typeof no_trailing !== 'boolean' ) {
133+
debounce_mode = callback;
134+
callback = no_trailing;
135+
no_trailing = undefined;
136+
}
137+
138+
// The `wrapper` function encapsulates all of the throttling / debouncing
139+
// functionality and when executed will limit the rate at which `callback`
140+
// is executed.
141+
function wrapper() {
142+
var that = this,
143+
elapsed = +new Date() - last_exec,
144+
args = arguments;
145+
146+
// Execute `callback` and update the `last_exec` timestamp.
147+
function exec() {
148+
last_exec = +new Date();
149+
callback.apply( that, args );
150+
};
151+
152+
// If `debounce_mode` is true (at_begin) this is used to clear the flag
153+
// to allow future `callback` executions.
154+
function clear() {
155+
timeout_id = undefined;
156+
};
157+
158+
if ( debounce_mode && !timeout_id ) {
159+
// Since `wrapper` is being called for the first time and
160+
// `debounce_mode` is true (at_begin), execute `callback`.
161+
exec();
162+
}
163+
164+
// Clear any existing timeout.
165+
timeout_id && clearTimeout( timeout_id );
166+
167+
if ( debounce_mode === undefined && elapsed > delay ) {
168+
// In throttle mode, if `delay` time has been exceeded, execute
169+
// `callback`.
170+
exec();
171+
172+
} else if ( no_trailing !== true ) {
173+
// In trailing throttle mode, since `delay` time has not been
174+
// exceeded, schedule `callback` to execute `delay` ms after most
175+
// recent execution.
176+
//
177+
// If `debounce_mode` is true (at_begin), schedule `clear` to execute
178+
// after `delay` ms.
179+
//
180+
// If `debounce_mode` is false (at end), schedule `callback` to
181+
// execute after `delay` ms.
182+
timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
183+
}
184+
};
185+
186+
// Set the guid of `wrapper` function to the same of original callback, so
187+
// it can be removed in jQuery 1.4+ .unbind or .die by using the original
188+
// callback as a reference.
189+
if ( $.guid ) {
190+
wrapper.guid = callback.guid = callback.guid || $.guid++;
191+
}
192+
193+
// Return the wrapper function.
194+
return wrapper;
195+
};
196+
197+
// Method: jQuery.debounce
198+
//
199+
// Debounce execution of a function. Debouncing, unlike throttling,
200+
// guarantees that a function is only executed a single time, either at the
201+
// very beginning of a series of calls, or at the very end. If you want to
202+
// simply rate-limit execution of a function, see the <jQuery.throttle>
203+
// method.
204+
//
205+
// In this visualization, | is a debounced-function call and X is the actual
206+
// callback execution:
207+
//
208+
// > Debounced with `at_begin` specified as false or unspecified:
209+
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
210+
// > X X
211+
// >
212+
// > Debounced with `at_begin` specified as true:
213+
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
214+
// > X X
215+
//
216+
// Usage:
217+
//
218+
// > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
219+
// >
220+
// > jQuery('selector').bind( 'someevent', debounced );
221+
// > jQuery('selector').unbind( 'someevent', debounced );
222+
//
223+
// This also works in jQuery 1.4+:
224+
//
225+
// > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
226+
// > jQuery('selector').unbind( 'someevent', callback );
227+
//
228+
// Arguments:
229+
//
230+
// delay - (Number) A zero-or-greater delay in milliseconds. For event
231+
// callbacks, values around 100 or 250 (or even higher) are most useful.
232+
// at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
233+
// unspecified, callback will only be executed `delay` milliseconds after
234+
// the last debounced-function call. If at_begin is true, callback will be
235+
// executed only at the first debounced-function call. (After the
236+
// throttled-function has not been called for `delay` milliseconds, the
237+
// internal counter is reset)
238+
// callback - (Function) A function to be executed after delay milliseconds.
239+
// The `this` context and all arguments are passed through, as-is, to
240+
// `callback` when the debounced-function is executed.
241+
//
242+
// Returns:
243+
//
244+
// (Function) A new, debounced, function.
245+
246+
$.debounce = function( delay, at_begin, callback ) {
247+
return callback === undefined
248+
? jq_throttle( delay, at_begin, false )
249+
: jq_throttle( delay, callback, at_begin !== false );
250+
};
251+
252+
})(this);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"uglify-js": "^3.4.9"
2727
},
2828
"scripts": {
29-
"uglify": "uglifyjs assets/js/vendor/jquery/jquery-3.3.1.min.js assets/js/plugins/jquery.fitvids.js assets/js/plugins/jquery.greedy-navigation.js assets/js/plugins/jquery.magnific-popup.js assets/js/plugins/jquery.smooth-scroll.min.js assets/js/_main.js -c -m -o assets/js/main.min.js",
29+
"uglify": "uglifyjs assets/js/vendor/jquery/jquery-3.3.1.min.js assets/js/plugins/jquery.fitvids.js assets/js/plugins/jquery.greedy-navigation.js assets/js/plugins/jquery.magnific-popup.js assets/js/plugins/jquery.smooth-scroll.min.js assets/js/plugins/jquery.ba-throttle-debounce.js assets/js/_main.js -c -m -o assets/js/main.min.js",
3030
"add-banner": "node banner.js",
3131
"watch:js": "onchange \"assets/js/**/*.js\" -e \"assets/js/main.min.js\" -- npm run build:js",
3232
"build:js": "npm run uglify && npm run add-banner"

0 commit comments

Comments
 (0)