Brian Silverman | dc6866b | 2018-08-05 00:18:23 -0700 | [diff] [blame^] | 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 | |
| 23 | (function($) { |
| 24 | /* |
| 25 | * The TOC plugin dynamically builds a table of contents from the headings in |
| 26 | * a document and prepends legal-style section numbers to each of the headings. |
| 27 | */ |
| 28 | $.fn.toc = function(options) { |
| 29 | var opts = $.extend({}, $.fn.toc.defaults, options); |
| 30 | |
| 31 | return this.each(function() { |
| 32 | var toc = $(this).append('<ul></ul>').children('ul'); |
| 33 | var headers = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0}; |
| 34 | var index = 0; |
| 35 | var indexes = { |
| 36 | h1: (opts.exclude.match('h1') == null && $('h1').length > 0) ? ++index : 0, |
| 37 | h2: (opts.exclude.match('h2') == null && $('h2').length > 0) ? ++index : 0, |
| 38 | h3: (opts.exclude.match('h3') == null && $('h3').length > 0) ? ++index : 0, |
| 39 | h4: (opts.exclude.match('h4') == null && $('h4').length > 0) ? ++index : 0, |
| 40 | h5: (opts.exclude.match('h5') == null && $('h5').length > 0) ? ++index : 0, |
| 41 | h6: (opts.exclude.match('h6') == null && $('h6').length > 0) ? ++index : 0 |
| 42 | }; |
| 43 | |
| 44 | $(':header').not(opts.exclude).each(function() { |
| 45 | var linkId = ""; |
| 46 | if ($(this).is('h6')) { |
| 47 | checkContainer(headers.h6, toc); |
| 48 | updateNumeration(headers, 'h6'); |
| 49 | $(this).text(addNumeration(headers, 'h6', $(this).text())); |
| 50 | linkId = fixAnchor($(this)); |
| 51 | appendToTOC(toc, indexes.h6, linkId, $(this).text(), headers); |
| 52 | } else if ($(this).is('h5')) { |
| 53 | checkContainer(headers.h5, toc); |
| 54 | updateNumeration(headers, 'h5'); |
| 55 | $(this).text(addNumeration(headers, 'h5', $(this).text())); |
| 56 | linkId = fixAnchor($(this)); |
| 57 | appendToTOC(toc, indexes.h5, linkId, $(this).text(), headers); |
| 58 | } else if ($(this).is('h4')) { |
| 59 | checkContainer(headers.h4, toc); |
| 60 | updateNumeration(headers, 'h4'); |
| 61 | $(this).text(addNumeration(headers, 'h4', $(this).text())); |
| 62 | linkId = fixAnchor($(this)); |
| 63 | appendToTOC(toc, indexes.h4, linkId, $(this).text(), headers); |
| 64 | } else if ($(this).is('h3')) { |
| 65 | checkContainer(headers.h3, toc); |
| 66 | updateNumeration(headers, 'h3'); |
| 67 | $(this).text(addNumeration(headers, 'h3', $(this).text())); |
| 68 | linkId = fixAnchor($(this)); |
| 69 | appendToTOC(toc, indexes.h3, linkId, $(this).text(), headers); |
| 70 | } else if ($(this).is('h2')) { |
| 71 | checkContainer(headers.h2, toc); |
| 72 | updateNumeration(headers, 'h2'); |
| 73 | $(this).text(addNumeration(headers, 'h2', $(this).text())); |
| 74 | linkId = fixAnchor($(this)); |
| 75 | appendToTOC(toc, indexes.h2, linkId, $(this).text(), headers); |
| 76 | } else if ($(this).is('h1')) { |
| 77 | updateNumeration(headers, 'h1'); |
| 78 | $(this).text(addNumeration(headers, 'h1', $(this).text())); |
| 79 | linkId = fixAnchor($(this)); |
| 80 | appendToTOC(toc, indexes.h1, linkId, $(this).text(), headers); |
| 81 | } |
| 82 | }); |
| 83 | }); |
| 84 | }; |
| 85 | |
| 86 | /* |
| 87 | * Checks if the last node is an 'ul' element. |
| 88 | * If not, a new one is created. |
| 89 | */ |
| 90 | function checkContainer(header, toc) { |
| 91 | if (header == 0 && !toc.find(':last').is('ul')) { |
| 92 | toc.find('li:last').append('<ul></ul>'); |
| 93 | } |
| 94 | }; |
| 95 | |
| 96 | /* |
| 97 | * Updates headers numeration. |
| 98 | */ |
| 99 | function updateNumeration(headers, header) { |
| 100 | $.each(headers, function(i, val) { |
| 101 | if (i == header) { |
| 102 | ++headers[i]; |
| 103 | } else if (i > header) { |
| 104 | headers[i] = 0; |
| 105 | } |
| 106 | }); |
| 107 | }; |
| 108 | |
| 109 | /* |
| 110 | * Prepends the numeration to a heading. |
| 111 | */ |
| 112 | function addNumeration(headers, header, text) { |
| 113 | var numeration = ''; |
| 114 | |
| 115 | $.each(headers, function(i, val) { |
| 116 | if (i <= header && headers[i] > 0) { |
| 117 | numeration += headers[i] + '.'; |
| 118 | } |
| 119 | }); |
| 120 | |
| 121 | return removeFinalDot(numeration) + ' ' + text; |
| 122 | }; |
| 123 | |
| 124 | function removeFinalDot(text) { |
| 125 | return (text||"").replace(/\.$/g, "" ) |
| 126 | } |
| 127 | |
| 128 | function fixAnchor(element) { |
| 129 | // use existing id by default |
| 130 | var linkId = element.attr('id'); |
| 131 | // next, look for an anchor and use its id or name |
| 132 | if ( !linkId ) { |
| 133 | element.find('> a:first').each( function() { |
| 134 | linkId = $(this).attr('id') || $(this).attr('name'); |
| 135 | }); |
| 136 | } |
| 137 | // next, use the text content as last resort |
| 138 | if ( !linkId ) { |
| 139 | linkId = (element.text()||"unknown").replace(/[^a-zA-Z0-9]/g,""); |
| 140 | } |
| 141 | |
| 142 | element.attr('id',linkId); |
| 143 | return linkId; |
| 144 | } |
| 145 | |
| 146 | /* |
| 147 | * Appends a new node to the TOC. |
| 148 | */ |
| 149 | function appendToTOC(toc, index, id, text, headers) { |
| 150 | var parent = toc; |
| 151 | |
| 152 | for (var i = 1; i < index; i++) { |
| 153 | if (parent.find('> li:last > ul').length == 0) { |
| 154 | parent = parent.append('<li><ul></ul></li>'); |
| 155 | } |
| 156 | parent = parent.find('> li:last > ul'); |
| 157 | } |
| 158 | if (id) { |
| 159 | parent.append('<li><a href="#' + id + '">' + text + '</a></li>'); |
| 160 | } else { |
| 161 | parent.append('<li>' + text + '</li>'); |
| 162 | } |
| 163 | }; |
| 164 | |
| 165 | $.fn.toc.defaults = {exclude: 'h1, h5, h6'} |
| 166 | })(jQuery); |