1/*! 2 * Bootstrap Table of Contents v<%= version %> (http://afeld.github.io/bootstrap-toc/) 3 * Copyright 2015 Aidan Feldman 4 * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5(function($) { 6 'use strict'; 7 8 window.Toc = { 9 helpers: { 10 // return all matching elements in the set, or their descendants 11 findOrFilter: function($el, selector) { 12 // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 // http://stackoverflow.com/a/12731439/358804 14 var $descendants = $el.find(selector); 15 return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 }, 17 18 generateUniqueIdBase: function(el) { 19 var text = $(el).text(); 20 var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 return anchor || el.tagName.toLowerCase(); 22 }, 23 24 generateUniqueId: function(el) { 25 var anchorBase = this.generateUniqueIdBase(el); 26 for (var i = 0; ; i++) { 27 var anchor = anchorBase; 28 if (i > 0) { 29 // add suffix 30 anchor += '-' + i; 31 } 32 // check if ID already exists 33 if (!document.getElementById(anchor)) { 34 return anchor; 35 } 36 } 37 }, 38 39 generateAnchor: function(el) { 40 if (el.id) { 41 return el.id; 42 } else { 43 var anchor = this.generateUniqueId(el); 44 el.id = anchor; 45 return anchor; 46 } 47 }, 48 49 createNavList: function() { 50 return $('<ul class="nav"></ul>'); 51 }, 52 53 createChildNavList: function($parent) { 54 var $childList = this.createNavList(); 55 $parent.append($childList); 56 return $childList; 57 }, 58 59 generateNavEl: function(anchor, text) { 60 var $a = $('<a></a>'); 61 $a.attr('href', '#' + anchor); 62 $a.text(text); 63 var $li = $('<li></li>'); 64 $li.append($a); 65 return $li; 66 }, 67 68 generateNavItem: function(headingEl) { 69 var anchor = this.generateAnchor(headingEl); 70 var $heading = $(headingEl); 71 var text = $heading.data('toc-text') || $heading.text(); 72 return this.generateNavEl(anchor, text); 73 }, 74 75 // Find the first heading level (`<h1>`, then `<h2>`, etc.) that has more than one element. Defaults to 1 (for `<h1>`). 76 getTopLevel: function($scope) { 77 for (var i = 1; i <= 6; i++) { 78 var $headings = this.findOrFilter($scope, 'h' + i); 79 if ($headings.length > 1) { 80 return i; 81 } 82 } 83 84 return 1; 85 }, 86 87 // returns the elements for the top level, and the next below it 88 getHeadings: function($scope, topLevel) { 89 var topSelector = 'h' + topLevel; 90 91 var secondaryLevel = topLevel + 1; 92 var secondarySelector = 'h' + secondaryLevel; 93 94 return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 }, 96 97 getNavLevel: function(el) { 98 return parseInt(el.tagName.charAt(1), 10); 99 }, 100 101 populateNav: function($topContext, topLevel, $headings) { 102 var $context = $topContext; 103 var $prevNav; 104 105 var helpers = this; 106 $headings.each(function(i, el) { 107 var $newNav = helpers.generateNavItem(el); 108 var navLevel = helpers.getNavLevel(el); 109 110 // determine the proper $context 111 if (navLevel === topLevel) { 112 // use top level 113 $context = $topContext; 114 } else if ($prevNav && $context === $topContext) { 115 // create a new level of the tree and switch to it 116 $context = helpers.createChildNavList($prevNav); 117 } // else use the current $context 118 119 $context.append($newNav); 120 121 $prevNav = $newNav; 122 }); 123 }, 124 125 parseOps: function(arg) { 126 var opts; 127 if (arg.jquery) { 128 opts = { 129 $nav: arg 130 }; 131 } else { 132 opts = arg; 133 } 134 opts.$scope = opts.$scope || $(document.body); 135 return opts; 136 } 137 }, 138 139 // accepts a jQuery object, or an options object 140 init: function(opts) { 141 opts = this.helpers.parseOps(opts); 142 143 // ensure that the data attribute is in place for styling 144 opts.$nav.attr('data-toggle', 'toc'); 145 146 var $topContext = this.helpers.createChildNavList(opts.$nav); 147 var topLevel = this.helpers.getTopLevel(opts.$scope); 148 var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 this.helpers.populateNav($topContext, topLevel, $headings); 150 } 151 }; 152 153 $(function() { 154 $('nav[data-toggle="toc"]').each(function(i, el) {
155 var $nav = $(el); 156 Toc.init($nav); 157 }); 158 }); 159})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.