toc.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. (function($) {
  2. $.fn.toc = function(options) {
  3. var self = this;
  4. var opts = $.extend({}, jQuery.fn.toc.defaults, options);
  5. var container = $(opts.container);
  6. var headings = $(opts.selectors, container);
  7. var headingOffsets = [];
  8. var activeClassName = opts.prefix+'-active';
  9. var scrollTo = function(e) {
  10. if (opts.smoothScrolling) {
  11. e.preventDefault();
  12. var elScrollTo = $(e.target).attr('href');
  13. var $el = $(elScrollTo);
  14. $('body,html').animate({ scrollTop: $el.offset().top }, 400, 'swing', function() {
  15. location.hash = elScrollTo;
  16. });
  17. }
  18. $('li', self).removeClass(activeClassName);
  19. $(e.target).parent().addClass(activeClassName);
  20. };
  21. //highlight on scroll
  22. var timeout;
  23. var highlightOnScroll = function(e) {
  24. if (timeout) {
  25. clearTimeout(timeout);
  26. }
  27. timeout = setTimeout(function() {
  28. var top = $(window).scrollTop(),
  29. highlighted;
  30. for (var i = 0, c = headingOffsets.length; i < c; i++) {
  31. if (headingOffsets[i] >= top) {
  32. $('li', self).removeClass(activeClassName);
  33. highlighted = $('li:eq('+(i-1)+')', self).addClass(activeClassName);
  34. opts.onHighlight(highlighted);
  35. break;
  36. }
  37. }
  38. }, 50);
  39. };
  40. if (opts.highlightOnScroll) {
  41. $(window).bind('scroll', highlightOnScroll);
  42. highlightOnScroll();
  43. }
  44. return this.each(function() {
  45. //build TOC
  46. var el = $(this);
  47. var ul = $('<ul/>');
  48. headings.each(function(i, heading) {
  49. var $h = $(heading);
  50. headingOffsets.push($h.offset().top - opts.highlightOffset);
  51. //add anchor
  52. var anchor = $('<span/>').attr('id', opts.anchorName(i, heading, opts.prefix)).insertBefore($h);
  53. //build TOC item
  54. var a = $('<a/>')
  55. .text(opts.headerText(i, heading, $h))
  56. .attr('href', '#' + opts.anchorName(i, heading, opts.prefix))
  57. .bind('click', function(e) {
  58. scrollTo(e);
  59. el.trigger('selected', $(this).attr('href'));
  60. });
  61. var li = $('<li/>')
  62. .addClass(opts.itemClass(i, heading, $h, opts.prefix))
  63. .append(a);
  64. ul.append(li);
  65. });
  66. el.html(ul);
  67. });
  68. };
  69. jQuery.fn.toc.defaults = {
  70. container: 'body',
  71. selectors: 'h1,h2,h3',
  72. smoothScrolling: true,
  73. prefix: 'toc',
  74. onHighlight: function() {},
  75. highlightOnScroll: true,
  76. highlightOffset: 100,
  77. anchorName: function(i, heading, prefix) {
  78. return prefix+i;
  79. },
  80. headerText: function(i, heading, $heading) {
  81. return $heading.text();
  82. },
  83. itemClass: function(i, heading, $heading, prefix) {
  84. return prefix + '-' + $heading[0].tagName.toLowerCase();
  85. }
  86. };
  87. })(jQuery);