aboutsummaryrefslogtreecommitdiff
path: root/docs/bootstrap-toc.js
diff options
context:
space:
mode:
Diffstat (limited to 'docs/bootstrap-toc.js')
-rw-r--r--docs/bootstrap-toc.js159
1 files changed, 159 insertions, 0 deletions
diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js
new file mode 100644
index 0000000..1cdd573
--- /dev/null
+++ b/docs/bootstrap-toc.js
@@ -0,0 +1,159 @@
+/*!
+ * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
+ * Copyright 2015 Aidan Feldman
+ * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
+(function() {
+ 'use strict';
+
+ window.Toc = {
+ helpers: {
+ // return all matching elements in the set, or their descendants
+ findOrFilter: function($el, selector) {
+ // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/
+ // http://stackoverflow.com/a/12731439/358804
+ var $descendants = $el.find(selector);
+ return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])');
+ },
+
+ generateUniqueIdBase: function(el) {
+ var text = $(el).text();
+ var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-');
+ return anchor || el.tagName.toLowerCase();
+ },
+
+ generateUniqueId: function(el) {
+ var anchorBase = this.generateUniqueIdBase(el);
+ for (var i = 0; ; i++) {
+ var anchor = anchorBase;
+ if (i > 0) {
+ // add suffix
+ anchor += '-' + i;
+ }
+ // check if ID already exists
+ if (!document.getElementById(anchor)) {
+ return anchor;
+ }
+ }
+ },
+
+ generateAnchor: function(el) {
+ if (el.id) {
+ return el.id;
+ } else {
+ var anchor = this.generateUniqueId(el);
+ el.id = anchor;
+ return anchor;
+ }
+ },
+
+ createNavList: function() {
+ return $('<ul class="nav"></ul>');
+ },
+
+ createChildNavList: function($parent) {
+ var $childList = this.createNavList();
+ $parent.append($childList);
+ return $childList;
+ },
+
+ generateNavEl: function(anchor, text) {
+ var $a = $('<a></a>');
+ $a.attr('href', '#' + anchor);
+ $a.text(text);
+ var $li = $('<li></li>');
+ $li.append($a);
+ return $li;
+ },
+
+ generateNavItem: function(headingEl) {
+ var anchor = this.generateAnchor(headingEl);
+ var $heading = $(headingEl);
+ var text = $heading.data('toc-text') || $heading.text();
+ return this.generateNavEl(anchor, text);
+ },
+
+ // Find the first heading level (`<h1>`, then `<h2>`, etc.) that has more than one element. Defaults to 1 (for `<h1>`).
+ getTopLevel: function($scope) {
+ for (var i = 1; i <= 6; i++) {
+ var $headings = this.findOrFilter($scope, 'h' + i);
+ if ($headings.length > 1) {
+ return i;
+ }
+ }
+
+ return 1;
+ },
+
+ // returns the elements for the top level, and the next below it
+ getHeadings: function($scope, topLevel) {
+ var topSelector = 'h' + topLevel;
+
+ var secondaryLevel = topLevel + 1;
+ var secondarySelector = 'h' + secondaryLevel;
+
+ return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
+ },
+
+ getNavLevel: function(el) {
+ return parseInt(el.tagName.charAt(1), 10);
+ },
+
+ populateNav: function($topContext, topLevel, $headings) {
+ var $context = $topContext;
+ var $prevNav;
+
+ var helpers = this;
+ $headings.each(function(i, el) {
+ var $newNav = helpers.generateNavItem(el);
+ var navLevel = helpers.getNavLevel(el);
+
+ // determine the proper $context
+ if (navLevel === topLevel) {
+ // use top level
+ $context = $topContext;
+ } else if ($prevNav && $context === $topContext) {
+ // create a new level of the tree and switch to it
+ $context = helpers.createChildNavList($prevNav);
+ } // else use the current $context
+
+ $context.append($newNav);
+
+ $prevNav = $newNav;
+ });
+ },
+
+ parseOps: function(arg) {
+ var opts;
+ if (arg.jquery) {
+ opts = {
+ $nav: arg
+ };
+ } else {
+ opts = arg;
+ }
+ opts.$scope = opts.$scope || $(document.body);
+ return opts;
+ }
+ },
+
+ // accepts a jQuery object, or an options object
+ init: function(opts) {
+ opts = this.helpers.parseOps(opts);
+
+ // ensure that the data attribute is in place for styling
+ opts.$nav.attr('data-toggle', 'toc');
+
+ var $topContext = this.helpers.createChildNavList(opts.$nav);
+ var topLevel = this.helpers.getTopLevel(opts.$scope);
+ var $headings = this.helpers.getHeadings(opts.$scope, topLevel);
+ this.helpers.populateNav($topContext, topLevel, $headings);
+ }
+ };
+
+ $(function() {
+ $('nav[data-toggle="toc"]').each(function(i, el) {
+ var $nav = $(el);
+ Toc.init($nav);
+ });
+ });
+})();

Contact - Imprint