199 lines
5.4 KiB
JavaScript
199 lines
5.4 KiB
JavaScript
/*
|
||
|
||
SMINT V1.0 by Robert McCracken
|
||
SMINT V2.0 by robert McCracken with some awesome help from Ryan Clarke (@clarkieryan) and mcpacosy (@mcpacosy)
|
||
SMINT V3.0 by robert McCracken with some awesome help from Ryan Clarke (@clarkieryan) and mcpacosy (@mcpacosy)
|
||
|
||
SMINT is my first dabble into jQuery plugins!
|
||
|
||
http://www.outyear.co.uk/smint/
|
||
|
||
If you like Smint, or have suggestions on how it could be improved, send me a tweet @rabmyself
|
||
|
||
*/
|
||
|
||
|
||
(function(){
|
||
|
||
|
||
$.fn.smint = function( options ) {
|
||
|
||
var settings = $.extend({
|
||
'scrollSpeed' : 500,
|
||
'mySelector' : 'div'
|
||
}, options);
|
||
|
||
// adding a class to users div
|
||
$(this).addClass('smint');
|
||
|
||
|
||
|
||
|
||
//Set the variables needed
|
||
var optionLocs = new Array(),
|
||
lastScrollTop = 0,
|
||
menuHeight = $(".smint").height(),
|
||
smint = $('.smint'),
|
||
smintA = $('.smint a'),
|
||
myOffset = smint.height();
|
||
|
||
|
||
|
||
|
||
|
||
if ( settings.scrollSpeed ) {
|
||
var scrollSpeed = settings.scrollSpeed
|
||
}
|
||
|
||
if ( settings.mySelector ) {
|
||
var mySelector = settings.mySelector
|
||
};
|
||
|
||
|
||
|
||
return smintA.each( function(index) {
|
||
|
||
var id = $(this).attr('href').split('#')[1];
|
||
|
||
if (!$(this).hasClass("extLink")) {
|
||
$(this).attr('id', id);
|
||
}
|
||
|
||
|
||
//Fill the menu
|
||
optionLocs.push(Array(
|
||
$(mySelector+"."+id).position().top-menuHeight,
|
||
$(mySelector+"."+id).height()+$(mySelector+"."+id).position().top, id)
|
||
);
|
||
|
||
///////////////////////////////////
|
||
|
||
// get initial top offset for the menu
|
||
var stickyTop = smint.offset().top;
|
||
|
||
// check position and make sticky if needed
|
||
var stickyMenu = function(direction){
|
||
|
||
// current distance top
|
||
var scrollTop = $(window).scrollTop()+myOffset;
|
||
|
||
// if we scroll more than the navigation, change its position to fixed and add class 'fxd', otherwise change it back to absolute and remove the class
|
||
if (scrollTop > stickyTop+myOffset) {
|
||
smint.css({ 'position': 'fixed', 'top':0,'left':0 }).addClass('fxd');
|
||
|
||
// add padding to the body to make up for the loss in heigt when the menu goes to a fixed position.
|
||
// When an item is fixed, its removed from the flow so its height doesnt impact the other items on the page
|
||
$('body').css('padding-top', menuHeight );
|
||
} else {
|
||
smint.css( 'position', 'relative').removeClass('fxd');
|
||
//remove the padding we added.
|
||
$('body').css('padding-top', '0' );
|
||
}
|
||
|
||
// Check if the position is inside then change the menu
|
||
// Courtesy of Ryan Clarke (@clarkieryan)
|
||
if(optionLocs[index][0] <= scrollTop && scrollTop <= optionLocs[index][1]){
|
||
if(direction == "up"){
|
||
$("#"+id).addClass("active");
|
||
$("#"+optionLocs[index+1][2]).removeClass("active");
|
||
} else if(index > 0) {
|
||
$("#"+id).addClass("active");
|
||
$("#"+optionLocs[index-1][2]).removeClass("active");
|
||
} else if(direction == undefined){
|
||
$("#"+id).addClass("active");
|
||
}
|
||
$.each(optionLocs, function(i){
|
||
if(id != optionLocs[i][2]){
|
||
|
||
$("#"+optionLocs[i][2]).removeClass("active");
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
// run functions
|
||
stickyMenu();
|
||
|
||
// run function every time you scroll
|
||
$(window).scroll(function() {
|
||
//Get the direction of scroll
|
||
var st = $(this).scrollTop()+myOffset;
|
||
if (st > lastScrollTop) {
|
||
direction = "down";
|
||
} else if (st < lastScrollTop ){
|
||
direction = "up";
|
||
}
|
||
lastScrollTop = st;
|
||
stickyMenu(direction);
|
||
|
||
// Check if at bottom of page, if so, add class to last <a> as sometimes the last div
|
||
// isnt long enough to scroll to the top of the page and trigger the active state.
|
||
|
||
if($(window).scrollTop() + $(window).height() == $(document).height()) {
|
||
smintA.removeClass('active')
|
||
$(".smint a:not('.extLink'):last").addClass('active')
|
||
|
||
} else {
|
||
smintA.last().removeClass('active')
|
||
}
|
||
});
|
||
|
||
|
||
///////////////////////////////////////
|
||
|
||
$(this).on('click', function(e){
|
||
// gets the height of the users div. This is used for off-setting the scroll so the menu doesnt overlap any content in the div they jst scrolled to
|
||
var myOffset = smint.height();
|
||
|
||
// stops hrefs making the page jump when clicked
|
||
e.preventDefault();
|
||
|
||
// get the hash of the button you just clicked
|
||
var hash = $(this).attr('href').split('#')[1];
|
||
|
||
|
||
|
||
var goTo = $(mySelector+'.'+ hash).offset().top-myOffset;
|
||
|
||
// Scroll the page to the desired position!
|
||
$("html, body").stop().animate({ scrollTop: goTo }, scrollSpeed);
|
||
|
||
// if the link has the '.extLink' class it will be ignored
|
||
// Courtesy of mcpacosy (@mcpacosy)
|
||
if ($(this).hasClass("extLink"))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
});
|
||
|
||
|
||
//This lets yo use links in body text to scroll. Just add the class 'intLink' to your button and it will scroll
|
||
|
||
$('.intLink').on('click', function(e){
|
||
var myOffset = smint.height();
|
||
|
||
e.preventDefault();
|
||
|
||
var hash = $(this).attr('href').split('#')[1];
|
||
|
||
if (smint.hasClass('fxd')) {
|
||
var goTo = $(mySelector+'.'+ hash).position().top-myOffset;
|
||
} else {
|
||
var goTo = $(mySelector+'.'+ hash).position().top-myOffset*2;
|
||
}
|
||
|
||
$("html, body").stop().animate({ scrollTop: goTo }, scrollSpeed);
|
||
|
||
if ($(this).hasClass("extLink"))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
});
|
||
});
|
||
|
||
};
|
||
|
||
$.fn.smint.defaults = { 'scrollSpeed': 500, 'mySelector': 'div'};
|
||
})(jQuery); |