Created
January 4, 2016 21:47
-
-
Save gautiermichelin/f3f76554c1a98fc6aa78 to your computer and use it in GitHub Desktop.
TOC jquery for CDN execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* toc - jQuery Table of Contents Plugin | |
* v0.3.2 | |
* http://projects.jga.me/toc/ | |
* copyright Greg Allen 2014 | |
* MIT License | |
*/ | |
/*! | |
* smooth-scroller - Javascript lib to handle smooth scrolling | |
* v0.1.2 | |
* https://github.com/firstandthird/smooth-scroller | |
* copyright First+Third 2014 | |
* MIT License | |
*/ | |
//smooth-scroller.js | |
(function($) { | |
$.fn.smoothScroller = function(options) { | |
options = $.extend({}, $.fn.smoothScroller.defaults, options); | |
var el = $(this); | |
$(options.scrollEl).animate({ | |
scrollTop: el.offset().top - $(options.scrollEl).offset().top - options.offset | |
}, options.speed, options.ease, function() { | |
var hash = el.attr('id'); | |
if(hash.length) { | |
if(history.pushState) { | |
history.pushState(null, null, '#' + hash); | |
} else { | |
document.location.hash = hash; | |
} | |
} | |
el.trigger('smoothScrollerComplete'); | |
}); | |
return this; | |
}; | |
$.fn.smoothScroller.defaults = { | |
speed: 400, | |
ease: 'swing', | |
scrollEl: 'body,html', | |
offset: 0 | |
}; | |
$('body').on('click', '[data-smoothscroller]', function(e) { | |
e.preventDefault(); | |
var href = $(this).attr('href'); | |
if(href.indexOf('#') === 0) { | |
$(href).smoothScroller(); | |
} | |
}); | |
}(jQuery)); | |
(function($) { | |
var verboseIdCache = {}; | |
$.fn.toc = function(options) { | |
var self = this; | |
var opts = $.extend({}, jQuery.fn.toc.defaults, options); | |
var container = $(opts.container); | |
var headings = $(opts.selectors, container); | |
var headingOffsets = []; | |
var activeClassName = opts.activeClass; | |
var scrollTo = function(e, callback) { | |
if (opts.smoothScrolling && typeof opts.smoothScrolling === 'function') { | |
e.preventDefault(); | |
var elScrollTo = $(e.target).attr('href'); | |
opts.smoothScrolling(elScrollTo, opts, callback); | |
} | |
$('li', self).removeClass(activeClassName); | |
$(e.target).parent().addClass(activeClassName); | |
}; | |
//highlight on scroll | |
var timeout; | |
var highlightOnScroll = function(e) { | |
if (timeout) { | |
clearTimeout(timeout); | |
} | |
timeout = setTimeout(function() { | |
var top = $(window).scrollTop(), | |
highlighted, closest = Number.MAX_VALUE, index = 0; | |
for (var i = 0, c = headingOffsets.length; i < c; i++) { | |
var currentClosest = Math.abs(headingOffsets[i] - top); | |
if (currentClosest < closest) { | |
index = i; | |
closest = currentClosest; | |
} | |
} | |
$('li', self).removeClass(activeClassName); | |
highlighted = $('li:eq('+ index +')', self).addClass(activeClassName); | |
opts.onHighlight(highlighted); | |
}, 50); | |
}; | |
if (opts.highlightOnScroll) { | |
$(window).bind('scroll', highlightOnScroll); | |
highlightOnScroll(); | |
} | |
return this.each(function() { | |
//build TOC | |
var el = $(this); | |
var ul = $(opts.listType); | |
headings.each(function(i, heading) { | |
var $h = $(heading); | |
headingOffsets.push($h.offset().top - opts.highlightOffset); | |
var anchorName = opts.anchorName(i, heading, opts.prefix); | |
//add anchor | |
if(heading.id !== anchorName) { | |
var anchor = $('<span/>').attr('id', anchorName).insertBefore($h); | |
} | |
//build TOC item | |
var a = $('<a/>') | |
.text(opts.headerText(i, heading, $h)) | |
.attr('href', '#' + anchorName) | |
.bind('click', function(e) { | |
$(window).unbind('scroll', highlightOnScroll); | |
scrollTo(e, function() { | |
$(window).bind('scroll', highlightOnScroll); | |
}); | |
el.trigger('selected', $(this).attr('href')); | |
}); | |
var li = $('<li/>') | |
.addClass(opts.itemClass(i, heading, $h, opts.prefix)) | |
.append(a); | |
ul.append(li); | |
}); | |
el.html(ul); | |
}); | |
}; | |
jQuery.fn.toc.defaults = { | |
container: 'body', | |
listType: '<ul/>', | |
selectors: 'h1,h2,h3', | |
smoothScrolling: function(target, options, callback) { | |
$(target).smoothScroller({ | |
offset: options.scrollToOffset | |
}).on('smoothScrollerComplete', function() { | |
callback(); | |
}); | |
}, | |
scrollToOffset: 0, | |
prefix: 'toc', | |
activeClass: 'toc-active', | |
onHighlight: function() {}, | |
highlightOnScroll: true, | |
highlightOffset: 100, | |
anchorName: function(i, heading, prefix) { | |
if(heading.id.length) { | |
return heading.id; | |
} | |
var candidateId = $(heading).text().replace(/[^a-z0-9]/ig, ' ').replace(/\s+/g, '-').toLowerCase(); | |
if (verboseIdCache[candidateId]) { | |
var j = 2; | |
while(verboseIdCache[candidateId + j]) { | |
j++; | |
} | |
candidateId = candidateId + '-' + j; | |
} | |
verboseIdCache[candidateId] = true; | |
return prefix + '-' + candidateId; | |
}, | |
headerText: function(i, heading, $heading) { | |
return $heading.text(); | |
}, | |
itemClass: function(i, heading, $heading, prefix) { | |
return prefix + '-' + $heading[0].tagName.toLowerCase(); | |
} | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment