sidenav.js 4.4 KB

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