Skip to content

Instantly share code, notes, and snippets.

@ArunMichaelDsouza
Last active September 6, 2015 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArunMichaelDsouza/a83c70f1b94f88519e67 to your computer and use it in GitHub Desktop.
Save ArunMichaelDsouza/a83c70f1b94f88519e67 to your computer and use it in GitHub Desktop.
oua.directive('affixMenu', ['$window', '$filter', function ($window, $filter) {
"use strict";
return {
restrict:'A',
replace:false,
transclude:false,
link:function (scope, element) {
var moveableHeight = element.height();
// add the menu links and heading positions to scope
scope.menuLinks = element.find('.nav a');
scope.menuHeadingPositions = [];
scope.scrolling = true;
// for each menu link, cache its heading and position
// on the current page so we can scroll to it
angular.forEach(scope.menuLinks, function (val) {
var $menuItem = $(val),
heading = $menuItem.attr('href');
scope.menuHeadingPositions.push({
id:heading,
position:$(heading).offset().top
});
});
// bind a click event to every link on the menu
// filtering by its target href, adding active
// state and smooth scrolling to the heading
// position on the page
scope.menuLinks.bind('click', function (e) {
e.preventDefault();
scope.scrolling = false;
var menuHeading = $filter('filter')(
scope.menuHeadingPositions,
{
id:$(this).attr('href')
}
)[0];
scope.menuLinks.removeClass('active');
$(this).addClass('active');
$('html,body').animate({scrollTop:menuHeading.position - 10}, 800, 'swing', function () {
scope.scrolling = true;
});
});
// bind the scroll function, so when we scroll past the menu
// it sticks to the top
var page = $('#page-main');
$($window).bind('scroll', scrollBind);
// moves the elements on the screen
// limiting the movement based on the size of the sidebar
function scrollBind() {
var scrollHeight = page.height() + page.offset().top,
scrollTop = $window.pageYOffset,
position = element.offset(),
offsetBottom = 0,
offsetTop = element.parent().offset().top,
reset = 'affix affix-top affix-bottom',
affix;
affix = scope.unpin != null && (scrollTop + scope.unpin <= position.top) ?
false : position.top + element.height() >= scrollHeight - offsetBottom ?
'bottom' : scrollTop <= offsetTop ?
'top' : false;
if (!affix && scope.scrolling) {
angular.forEach(scope.menuHeadingPositions, function (val) {
if (scrollTop >= (val.position - 10)) {
scope.menuLinks.filter('[href="' + val.id + '"]').addClass('active');
scope.menuLinks.filter('[href!="' + val.id + '"]').removeClass('active');
}
});
}
if (scope.affixed === affix) return;
scope.affixed = affix;
scope.unpin = affix == 'bottom' ? position.top - scrollTop : null;
element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''));
}
}
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment