aboutsummaryrefslogtreecommitdiff
path: root/doc/scripts/toc.js
diff options
context:
space:
mode:
authorMarak <[email protected]>2016-03-03 04:38:00 -0500
committerMarak <[email protected]>2016-03-03 04:38:00 -0500
commitaff89dcfbf8611473a1dabb6a6cb1ad17ae34d47 (patch)
tree301a4d899c0c49af0e4e1b859342a740c5158bf2 /doc/scripts/toc.js
parentc252feb52e896f153fd969377532d77777903d69 (diff)
downloadfaker-aff89dcfbf8611473a1dabb6a6cb1ad17ae34d47.tar.xz
faker-aff89dcfbf8611473a1dabb6a6cb1ad17ae34d47.zip
[dist] Check /docs back into git #350
Diffstat (limited to 'doc/scripts/toc.js')
-rw-r--r--doc/scripts/toc.js203
1 files changed, 203 insertions, 0 deletions
diff --git a/doc/scripts/toc.js b/doc/scripts/toc.js
new file mode 100644
index 00000000..e5151284
--- /dev/null
+++ b/doc/scripts/toc.js
@@ -0,0 +1,203 @@
+(function($) {
+ var navbarHeight;
+ var initialised = false;
+ var navbarOffset;
+
+ function elOffset($el) {
+ return $el.offset().top - (navbarHeight + navbarOffset);
+ }
+
+ function scrollToHash(duringPageLoad) {
+ var elScrollToId = location.hash.replace(/^#/, '');
+ var $el;
+
+ function doScroll() {
+ var offsetTop = elOffset($el);
+ window.scrollTo(window.pageXOffset || window.scrollX, offsetTop);
+ }
+
+ if (elScrollToId) {
+ $el = $(document.getElementById(elScrollToId));
+
+ if (!$el.length) {
+ $el = $(document.getElementsByName(elScrollToId));
+ }
+
+ if ($el.length) {
+ if (duringPageLoad) {
+ $(window).one('scroll', function() {
+ setTimeout(doScroll, 100);
+ });
+ } else {
+ setTimeout(doScroll, 0);
+ }
+ }
+ }
+ }
+
+ function init(opts) {
+ if (initialised) {
+ return;
+ }
+ initialised = true;
+ navbarHeight = $('.navbar').height();
+ navbarOffset = opts.navbarOffset;
+
+ // some browsers move the offset after changing location.
+ // also catch external links coming in
+ $(window).on("hashchange", scrollToHash.bind(null, false));
+ $(scrollToHash.bind(null, true));
+ }
+
+ $.catchAnchorLinks = function(options) {
+ var opts = $.extend({}, jQuery.fn.toc.defaults, options);
+ init(opts);
+ };
+
+ $.fn.toc = function(options) {
+ var self = this;
+ var opts = $.extend({}, jQuery.fn.toc.defaults, options);
+
+ var container = $(opts.container);
+ var tocs = [];
+ var headings = $(opts.selectors, container);
+ var headingOffsets = [];
+ var activeClassName = 'active';
+ var ANCHOR_PREFIX = "__anchor";
+ var maxScrollTo;
+ var visibleHeight;
+ var headerHeight = 10; // so if the header is readable, its counted as shown
+ init();
+
+ var scrollTo = function(e) {
+ e.preventDefault();
+ var target = $(e.target);
+ if (target.prop('tagName').toLowerCase() !== "a") {
+ target = target.parent();
+ }
+ var elScrollToId = target.attr('href').replace(/^#/, '') + ANCHOR_PREFIX;
+ var $el = $(document.getElementById(elScrollToId));
+
+ var offsetTop = Math.min(maxScrollTo, elOffset($el));
+
+ $('body,html').animate({ scrollTop: offsetTop }, 400, 'swing', function() {
+ location.hash = '#' + elScrollToId;
+ });
+
+ $('a', self).removeClass(activeClassName);
+ target.addClass(activeClassName);
+ };
+
+ var calcHadingOffsets = function() {
+ maxScrollTo = $("body").height() - $(window).height();
+ visibleHeight = $(window).height() - navbarHeight;
+ headingOffsets = [];
+ headings.each(function(i, heading) {
+ var anchorSpan = $(heading).prev("span");
+ var top = 0;
+ if (anchorSpan.length) {
+ top = elOffset(anchorSpan);
+ }
+ headingOffsets.push(top > 0 ? top : 0);
+ });
+ }
+
+ //highlight on scroll
+ var timeout;
+ var highlightOnScroll = function(e) {
+ if (!tocs.length) {
+ return;
+ }
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ timeout = setTimeout(function() {
+ var top = $(window).scrollTop(),
+ highlighted;
+ for (var i = headingOffsets.length - 1; i >= 0; i--) {
+ var isActive = tocs[i].hasClass(activeClassName);
+ // at the end of the page, allow any shown header
+ if (isActive && headingOffsets[i] >= maxScrollTo && top >= maxScrollTo) {
+ return;
+ }
+ // if we have got to the first heading or the heading is the first one visible
+ if (i === 0 || (headingOffsets[i] + headerHeight >= top && (headingOffsets[i - 1] + headerHeight <= top))) {
+ // in the case that a heading takes up more than the visible height e.g. we are showing
+ // only the one above, highlight the one above
+ if (i > 0 && headingOffsets[i] - visibleHeight >= top) {
+ i--;
+ }
+ $('a', self).removeClass(activeClassName);
+ if (i >= 0) {
+ highlighted = tocs[i].addClass(activeClassName);
+ opts.onHighlight(highlighted);
+ }
+ break;
+ }
+ }
+ }, 50);
+ };
+ if (opts.highlightOnScroll) {
+ $(window).bind('scroll', highlightOnScroll);
+ $(window).bind('load resize', function() {
+ calcHadingOffsets();
+ highlightOnScroll();
+ });
+ }
+
+ return this.each(function() {
+ //build TOC
+ var el = $(this);
+ var ul = $('<div class="list-group">');
+
+ headings.each(function(i, heading) {
+ var $h = $(heading);
+
+ var anchor = $('<span/>').attr('id', opts.anchorName(i, heading, opts.prefix) + ANCHOR_PREFIX).insertBefore($h);
+
+ var span = $('<span/>')
+ .text(opts.headerText(i, heading, $h));
+
+ //build TOC item
+ var a = $('<a class="list-group-item"/>')
+ .append(span)
+ .attr('href', '#' + opts.anchorName(i, heading, opts.prefix))
+ .bind('click', function(e) {
+ scrollTo(e);
+ el.trigger('selected', $(this).attr('href'));
+ });
+
+ span.addClass(opts.itemClass(i, heading, $h, opts.prefix));
+
+ tocs.push(a);
+
+ ul.append(a);
+ });
+ el.html(ul);
+
+ calcHadingOffsets();
+ });
+};
+
+
+jQuery.fn.toc.defaults = {
+ container: 'body',
+ selectors: 'h1,h2,h3',
+ smoothScrolling: true,
+ prefix: 'toc',
+ onHighlight: function() {},
+ highlightOnScroll: true,
+ navbarOffset: 0,
+ anchorName: function(i, heading, prefix) {
+ return prefix+i;
+ },
+ headerText: function(i, heading, $heading) {
+ return $heading.text();
+ },
+ itemClass: function(i, heading, $heading, prefix) {
+ return prefix + '-' + $heading[0].tagName.toLowerCase();
+ }
+
+};
+
+})(jQuery);