Skip to content

Instantly share code, notes, and snippets.

@monomial
Forked from nwpappas/angularScrollSpy.js
Last active August 29, 2015 14:24
Show Gist options
  • Save monomial/d8f5797c05b8d3e1429a to your computer and use it in GitHub Desktop.
Save monomial/d8f5797c05b8d3e1429a to your computer and use it in GitHub Desktop.
fork of EvilClosetMonkey's angularScrollSpy.js which is based on axhill's scrollspy.coffee. Closely mimics the Bootstrap ScrollSpy plugin in Angular.
/*
* Angular ScrollSpy directive
*
* When used with ngView / ngRoute, don't forget to set `reloadOnSearch` to false in the $routeProvider.when parameters
* https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
*
* Use $anchorScroll.yOffset to provide an offset for a navigation bar at the top of the screen
*/
(function ($) {
'use strict';
angular.module("mjs.angularScrollSpy", []).directive('scrollSpy', [
'$window', '$document', '$anchorScroll', function ($window, $document, $anchorScroll) {
return {
restrict: 'A',
controller: function ($scope) {
$scope.spies = [];
this.addSpy = function (spyObj) {
$scope.spies.push(spyObj);
};
},
link: function (scope, elem, attrs) {
var spyElems, // the elements being spied upon (jQuery objects)
$$window;
spyElems = [];
$$window = $($window);
scope.$watchCollection('spies', function (spies) {
var spy, i, spyCount;
spyCount = spies.length;
for (i = 0; i < spyCount; i++) {
spy = spies[i];
if (spyElems[spy.id] == null) {
spyElems[spy.id] = elem.find('#' + spy.id);
}
}
});
$$window.scroll(function () {
var highlightSpy, pos, spy, i, spyCount, scrollTopPlusOffset;
highlightSpy = null;
spyCount = scope.spies.length;
scrollTopPlusOffset = $$window.scrollTop() + $anchorScroll.yOffset;
// cycle through `spy` elements to find which to highlight
for (i = 0; i < spyCount; i++) {
spy = scope.spies[i];
spy.deactivate();
// catch case where a `spy` does not have an associated `id` anchor
if (spyElems[spy.id].offset() === undefined) {
continue;
}
if ((pos = spyElems[spy.id].offset().top) - scrollTopPlusOffset <= 0) {
// the window (plus offset) has been scrolled past the top of a spy element
spy.pos = pos;
if (highlightSpy == null || spy.pos > highlightSpy.pos) {
highlightSpy = spy;
}
}
}
// select the last `spy` if the scrollbar is at the bottom of the page
if ($$window.scrollTop() + $$window.height() >= $document.height()) {
spy.pos = pos;
highlightSpy = spy;
}
if (highlightSpy) {
highlightSpy.activate();
}
});
}
};
}]).directive('spy', ['$location', '$anchorScroll', function ($location, $anchorScroll) {
return {
restrict: "A",
require: "^scrollSpy",
link: function (scope, elem, attrs, scrollSpy) {
elem.click(function () {
scope.$applyAsync(function () {
$location.hash(attrs.spy);
});
});
scrollSpy.addSpy({
id: attrs.spy,
activate: function () {
elem.addClass('active');
},
deactivate: function () {
elem.removeClass('active');
}
});
}
};
}]);
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment