sidenav.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * @file sidenav.js
  3. * @author Jianlong Chen <jianlong99@gmail.com>
  4. * @date 2014-03-08
  5. * @update 2014-11-12
  6. */
  7. (function($) {
  8. 'use strict';
  9. function SideNav($el) {
  10. this.$el = $el;
  11. }
  12. SideNav.prototype = {
  13. constructor: SideNav,
  14. init: function(options) {
  15. this.options = options;
  16. this.initViews();
  17. this.initAffix();
  18. },
  19. initViews: function() {
  20. var that = this,
  21. counts = {},
  22. preLevel = 0;
  23. this.$menu = $([
  24. '<div class="bs-sidebar hidden-print">',
  25. ' <ul class="nav bs-sidenav">',
  26. ' </ul>',
  27. '</div>'
  28. ].join(''));
  29. this.$list = '';
  30. // Support String type, for example use: data-hs="h1, h2, h3"
  31. if (typeof this.options.hs === 'string') {
  32. this.options.hs = $.map(this.options.hs.split(','), function (h) {
  33. return $.trim(h); // remove space
  34. });
  35. }
  36. this.$el.find(this.options.hs.join(',')).each(function(i) {
  37. var $this = $(this),
  38. $div,
  39. name = $this[0].localName,
  40. title = $this.text(),
  41. level = $.inArray(name, that.options.hs) + 1,
  42. nums = [],
  43. index,
  44. id;
  45. if (level - preLevel > 1) {
  46. return;
  47. }
  48. if (!counts.hasOwnProperty(name) || level - preLevel === 1) {
  49. counts[name] = 0;
  50. }
  51. counts[name]++;
  52. $.each(counts, function(i) {
  53. nums.push(counts[i]);
  54. if (nums.length === level) {
  55. return false;
  56. }
  57. });
  58. index = nums.join('-');
  59. id = 'sideNavTitle' + index;
  60. if (that.options.smartId) {
  61. id = $.trim($(this).text()).toLowerCase();
  62. id = id.replace(/ /g, '-');
  63. id = id.replace(/'|"/g, '');
  64. }
  65. $div = $('<div id="' + id + '"></div>');
  66. $div.insertAfter($this).append($this);
  67. var aElem = '<a href="#' + id + '">' + title + '</a>';
  68. if (level === 1 && preLevel === 0) {
  69. that.$list += '<li class="active">' + aElem;
  70. } else if (level === preLevel) {
  71. that.$list += '</li><li>' + aElem;
  72. } else if (level - preLevel === 1) {
  73. that.$list += '<ul class="nav"><li>' + aElem;
  74. } else {
  75. for (var $i = 0; $i < preLevel - level; $i++) {
  76. that.$list += '</ul></li>';
  77. }
  78. that.$list += '<li>' + aElem;
  79. }
  80. preLevel = level;
  81. });
  82. for (; preLevel > 0; preLevel--) {
  83. if (preLevel > 1) {
  84. that.$list += '</ul>';
  85. }
  86. that.$list += '</li>';
  87. }
  88. this.$menu.find('ul').append(this.$list);
  89. var backElem = '<a class="back-to-top" href="' +
  90. this.options.toTopHref + '">' + this.options.toTopText + '</a>';
  91. this.$menu.append(backElem);
  92. $(this.options.container).append(this.$menu);
  93. },
  94. initAffix: function() {
  95. $('body').scrollspy({target: '.bs-sidebar'});
  96. if (typeof this.options.top === 'undefined') {
  97. this.options.top = this.options.container;
  98. }
  99. if (typeof this.options.top === 'string' && $(this.options.top).length) {
  100. this.options.top = $(this.options.top).offset().top;
  101. }
  102. if (typeof this.options.bottom === 'string' && $(this.options.bottom).length) {
  103. this.options.bottom = $(this.options.bottom).outerHeight(true);
  104. }
  105. this.$menu.affix({
  106. offset: {
  107. top: this.options.top || 0,
  108. bottom: this.options.bottom || 0
  109. }
  110. });
  111. }
  112. };
  113. $.fn.sideNav = function() {
  114. var option = arguments[0],
  115. args = arguments,
  116. value;
  117. this.each(function() {
  118. var $this = $(this), data = $this.data('sideNav'),
  119. options = $.extend({}, $.fn.sideNav.defaults, $this.data(), option);
  120. if (!data) {
  121. data = new SideNav($this);
  122. data.init(options, true);
  123. $this.data('sideNav', data);
  124. } else {
  125. data.init(options);
  126. }
  127. });
  128. return value ? value : this;
  129. };
  130. $.fn.sideNav.defaults = {
  131. container: 'body',
  132. hs: ['h2', 'h3', 'h4'],
  133. smartId: false,
  134. top: undefined,
  135. bottom: undefined,
  136. toTopHref: '#top',
  137. toTopText: 'Back to top'
  138. };
  139. $(function () {
  140. $('[data-toggle="sidenav"]').sideNav();
  141. });
  142. })(jQuery);