jquery.toc-gw.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*!
  2. * jQuery TOC Plugin v1.1.x based on
  3. * samaxesJS JavaScript Library
  4. * http://code.google.com/p/samaxesjs/
  5. *
  6. * Copyright (c) 2008 samaxes.com
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. * 2009-10-04, guwi17: modified and extended to meet uBLAS' needs
  21. */
  22. (function($) {
  23. /*
  24. * The TOC plugin dynamically builds a table of contents from the headings in
  25. * a document and prepends legal-style section numbers to each of the headings.
  26. */
  27. $.fn.toc = function(options) {
  28. var opts = $.extend({}, $.fn.toc.defaults, options);
  29. return this.each(function() {
  30. var toc = $(this).append('<ul></ul>').children('ul');
  31. var headers = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0};
  32. var index = 0;
  33. var indexes = {
  34. h1: (opts.exclude.match('h1') == null && $('h1').length > 0) ? ++index : 0,
  35. h2: (opts.exclude.match('h2') == null && $('h2').length > 0) ? ++index : 0,
  36. h3: (opts.exclude.match('h3') == null && $('h3').length > 0) ? ++index : 0,
  37. h4: (opts.exclude.match('h4') == null && $('h4').length > 0) ? ++index : 0,
  38. h5: (opts.exclude.match('h5') == null && $('h5').length > 0) ? ++index : 0,
  39. h6: (opts.exclude.match('h6') == null && $('h6').length > 0) ? ++index : 0
  40. };
  41. $(':header').not(opts.exclude).each(function() {
  42. var linkId = "";
  43. if ($(this).is('h6')) {
  44. checkContainer(headers.h6, toc);
  45. updateNumeration(headers, 'h6');
  46. $(this).text(addNumeration(headers, 'h6', $(this).text()));
  47. linkId = fixAnchor($(this));
  48. appendToTOC(toc, indexes.h6, linkId, $(this).text(), headers);
  49. } else if ($(this).is('h5')) {
  50. checkContainer(headers.h5, toc);
  51. updateNumeration(headers, 'h5');
  52. $(this).text(addNumeration(headers, 'h5', $(this).text()));
  53. linkId = fixAnchor($(this));
  54. appendToTOC(toc, indexes.h5, linkId, $(this).text(), headers);
  55. } else if ($(this).is('h4')) {
  56. checkContainer(headers.h4, toc);
  57. updateNumeration(headers, 'h4');
  58. $(this).text(addNumeration(headers, 'h4', $(this).text()));
  59. linkId = fixAnchor($(this));
  60. appendToTOC(toc, indexes.h4, linkId, $(this).text(), headers);
  61. } else if ($(this).is('h3')) {
  62. checkContainer(headers.h3, toc);
  63. updateNumeration(headers, 'h3');
  64. $(this).text(addNumeration(headers, 'h3', $(this).text()));
  65. linkId = fixAnchor($(this));
  66. appendToTOC(toc, indexes.h3, linkId, $(this).text(), headers);
  67. } else if ($(this).is('h2')) {
  68. checkContainer(headers.h2, toc);
  69. updateNumeration(headers, 'h2');
  70. $(this).text(addNumeration(headers, 'h2', $(this).text()));
  71. linkId = fixAnchor($(this));
  72. appendToTOC(toc, indexes.h2, linkId, $(this).text(), headers);
  73. } else if ($(this).is('h1')) {
  74. updateNumeration(headers, 'h1');
  75. $(this).text(addNumeration(headers, 'h1', $(this).text()));
  76. linkId = fixAnchor($(this));
  77. appendToTOC(toc, indexes.h1, linkId, $(this).text(), headers);
  78. }
  79. });
  80. });
  81. };
  82. /*
  83. * Checks if the last node is an 'ul' element.
  84. * If not, a new one is created.
  85. */
  86. function checkContainer(header, toc) {
  87. if (header == 0 && !toc.find(':last').is('ul')) {
  88. toc.find('li:last').append('<ul></ul>');
  89. }
  90. };
  91. /*
  92. * Updates headers numeration.
  93. */
  94. function updateNumeration(headers, header) {
  95. $.each(headers, function(i, val) {
  96. if (i == header) {
  97. ++headers[i];
  98. } else if (i > header) {
  99. headers[i] = 0;
  100. }
  101. });
  102. };
  103. /*
  104. * Prepends the numeration to a heading.
  105. */
  106. function addNumeration(headers, header, text) {
  107. var numeration = '';
  108. $.each(headers, function(i, val) {
  109. if (i <= header && headers[i] > 0) {
  110. numeration += headers[i] + '.';
  111. }
  112. });
  113. return removeFinalDot(numeration) + ' ' + text;
  114. };
  115. function removeFinalDot(text) {
  116. return (text||"").replace(/\.$/g, "" )
  117. }
  118. function fixAnchor(element) {
  119. // use existing id by default
  120. var linkId = element.attr('id');
  121. // next, look for an anchor and use its id or name
  122. if ( !linkId ) {
  123. element.find('> a:first').each( function() {
  124. linkId = $(this).attr('id') || $(this).attr('name');
  125. });
  126. }
  127. // next, use the text content as last resort
  128. if ( !linkId ) {
  129. linkId = (element.text()||"unknown").replace(/[^a-zA-Z0-9]/g,"");
  130. }
  131. element.attr('id',linkId);
  132. return linkId;
  133. }
  134. /*
  135. * Appends a new node to the TOC.
  136. */
  137. function appendToTOC(toc, index, id, text, headers) {
  138. var parent = toc;
  139. for (var i = 1; i < index; i++) {
  140. if (parent.find('> li:last > ul').length == 0) {
  141. parent = parent.append('<li><ul></ul></li>');
  142. }
  143. parent = parent.find('> li:last > ul');
  144. }
  145. if (id) {
  146. parent.append('<li><a href="#' + id + '">' + text + '</a></li>');
  147. } else {
  148. parent.append('<li>' + text + '</li>');
  149. }
  150. };
  151. $.fn.toc.defaults = {exclude: 'h1, h5, h6'}
  152. })(jQuery);