200 lines
6.6 KiB
JavaScript
200 lines
6.6 KiB
JavaScript
|
|
;(function ($, window, document, undefined) {
|
|
|
|
// Add our plugin to fn
|
|
$.fn.extend({
|
|
|
|
// Scrollspy is the name of the plugin
|
|
scrollspy: function (options) {
|
|
|
|
// Define our defaults
|
|
var defaults = {
|
|
namespace: 'scrollspy',
|
|
activeClass: 'active',
|
|
scrollSpeed: 500,
|
|
offset: 0,
|
|
container: window,
|
|
onChange: function(){},
|
|
onExit: function(){}
|
|
};
|
|
|
|
// Add any overriden options to a new object
|
|
options = $.extend({}, defaults, options);
|
|
|
|
// Adds two numbers together
|
|
var add = function (ex1, ex2) {
|
|
return parseInt(ex1, 10) + parseInt(ex2, 10);
|
|
}
|
|
|
|
// Find our elements
|
|
var findElements = function (links) {
|
|
|
|
// Declare our array
|
|
var elements = [];
|
|
|
|
// Loop through the links
|
|
for (var i = 0; i < links.length; i++) {
|
|
|
|
// Get our current link
|
|
var link = links[i];
|
|
|
|
// Get our hash
|
|
var hash = $(link).attr("href");
|
|
|
|
// Store our hash as an element
|
|
var element = $(hash);
|
|
|
|
// If we have an element matching the hash
|
|
if (element.length > 0) {
|
|
|
|
// Get our offset
|
|
var top = Math.floor(element.offset().top),
|
|
bottom = top + Math.floor(element.outerHeight());
|
|
|
|
// Add to our array
|
|
elements.push({ element: element, hash: hash, top: top, bottom: bottom });
|
|
}
|
|
}
|
|
|
|
// Return our elements
|
|
return elements;
|
|
};
|
|
|
|
// Find our link from a hash
|
|
var findLink = function (links, hash) {
|
|
|
|
// For each link
|
|
for (var i = 0; i < links.length; i++) {
|
|
|
|
// Get our current link
|
|
var link = $(links[i]);
|
|
|
|
// If our hash matches the link href
|
|
if (link.attr("href") === hash) {
|
|
|
|
// Return the link
|
|
return link;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Reset classes on our elements
|
|
var resetClasses = function (links) {
|
|
|
|
// For each link
|
|
for (var i = 0; i < links.length; i++) {
|
|
|
|
// Get our current link
|
|
var link = $(links[i]);
|
|
|
|
// Remove the active class
|
|
link.parent().removeClass(options.activeClass);
|
|
}
|
|
};
|
|
|
|
// For each scrollspy instance
|
|
return this.each(function () {
|
|
|
|
// Declare our global variables
|
|
var element = this,
|
|
container = $(options.container);
|
|
|
|
// Get our objects
|
|
var links = $(element).find(".nav-menu").find('[href*="#"]');
|
|
|
|
// Loop through our links
|
|
for (var i = 0; i < links.length; i++) {
|
|
|
|
// Get our current link
|
|
var link = links[i];
|
|
|
|
// Bind the click event
|
|
$(link).on("click", function (e) {
|
|
|
|
// Get our target
|
|
var target = $(this).attr("href"),
|
|
$target = $(target);
|
|
|
|
// If we have the element
|
|
if ($target.length > 0) {
|
|
|
|
// Get it's scroll position
|
|
var top = add($target.offset().top, options.offset);
|
|
|
|
// Scroll to our position
|
|
$('html, body').animate({ scrollTop: top }, options.scrollSpeed);
|
|
|
|
// Prevent our link
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get our elements
|
|
var elements = findElements(links);
|
|
|
|
$(window).resize(function() {
|
|
elements = findElements(links);
|
|
});
|
|
|
|
// Add a listener to the window
|
|
container.on('scroll.' + options.namespace, function () {
|
|
|
|
// Get the position and store in an object
|
|
var position = {
|
|
top: add($(this).scrollTop(), Math.abs(options.offset)),
|
|
left: $(this).scrollLeft()
|
|
};
|
|
|
|
// Create a variable for our link
|
|
var link;
|
|
|
|
// Loop through our elements
|
|
for (var i = 0; i < elements.length; i++) {
|
|
|
|
// Get our current item
|
|
var current = elements[i];
|
|
|
|
// If we are within the boundries of our element
|
|
if (position.top >= current.top && position.top < current.bottom) {
|
|
|
|
// get our element
|
|
var hash = current.hash;
|
|
|
|
// Get the link
|
|
link = findLink(links, hash);
|
|
|
|
// If we have a link
|
|
if (link) {
|
|
|
|
// If we have an onChange function
|
|
if (options.onChange) {
|
|
|
|
// Fire our onChange function
|
|
options.onChange(current.element, $(element), position);
|
|
}
|
|
|
|
// Reset the classes on all other link
|
|
resetClasses(links);
|
|
|
|
// Add our active link to our parent
|
|
link.parent().addClass(options.activeClass);
|
|
|
|
// break our loop
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we don't have a link and we have a exit function
|
|
if (!link && options.onExit) {
|
|
|
|
// Fire our onChange function
|
|
options.onExit($(element), position);
|
|
}
|
|
});
|
|
|
|
});
|
|
}
|
|
});
|
|
})(jQuery, window, document, undefined); |