-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjquery.stickyMenu.js
93 lines (81 loc) · 3.15 KB
/
jquery.stickyMenu.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* jQuery Sticky Menu Plugin v0.1
* http://
*
* Copyright (c) 2010 Bearded Studio LLC
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Depends on:
* jQuery Sticky http://github.com/michaek/jquery.sticky
* jQuery Address http://www.asual.com/jquery/address/
*/
(function($){
$.fn.stickyMenu = function(options){
options = $.extend({
containedBy: null, // dom element that restricts scrolling of navigation
distanceFromTop: 0,
activeClass: 'active'
}, options);
// loop over the selected elements
this.each(function(){
var $stickyMenu = $(this);
var $stickyLinks = $stickyMenu.find('a[href^=#]');
// we'll keep track of whether we just clicked the menu
var listenForScroll = false;
$stickyLinks.click(function(){ listenForScroll = false; });
var activateLinksOnScroll = function(){
var scrollOffset = $(this).scrollTop();
var $active = null;
var $activeLink = null;
// since we're scrolling, we should listen for scrolling!
listenForScroll = true;
// we want to get the active link, but this is not the efficient way!
// TODO: optimize even just a little
$stickyLinks.each(function(){
var $link = $(this);
var $target = $($link.attr('href'));
if ($target.length) {
// ignore everything that's beyond the current scroll
if ($target.offset().top > scrollOffset) {
return;
}
// if this target is further down the page than a previous target, use it
if (!$active || $target.offset().top > $active.offset().top) {
$active = $target;
$activeLink = $link;
}
}
});
// update address with the current value
if ($active) {
$.address.value($activeLink.attr('href').replace(/^#/, ''));
}
}
// on the change event for address
$.address.change(function(event) {
var targetSelector = event.path.replace(/^\//, '#');
var $target = $(targetSelector);
var $link = $stickyLinks.filter('[href='+targetSelector+']');
$stickyLinks.removeClass(options.activeClass);
$link.addClass(options.activeClass);
// only start scrolling if we're not listening for scrolling
if (!listenForScroll) {
// unbind the scroll function to avoid conflicts
$(window).unbind('scroll', activateLinksOnScroll);
// scroll to the target element
$('body').animate({scrollTop: $target.offset().top}, 250, function(){
// re-bind the scroll function when the animation has completed
$(window).scroll(activateLinksOnScroll);
});
}
});
// invoke sticky on the menu
$stickyMenu.sticky({containedBy: options.containedBy, distanceFromTop: options.distanceFromTop});
// invoke address on our menu links
$stickyLinks.address();
// listen to the scroll to activate menu links
$(window).scroll(activateLinksOnScroll);
});
}
})(jQuery);