]> git.0d.be Git - chloro.git/blobdiff - chloro/phyll/static/js/chloro.js
add support for a dynamic table of contents
[chloro.git] / chloro / phyll / static / js / chloro.js
index dd95885422dde9cb4b0e17bc33ace2519d15c71b..dc0015a03d19205176a4f9e0bd67793798145250 100644 (file)
@@ -33,6 +33,51 @@ function auto_anchors() {
   });
 }
 
+function create_toc() {
+  $('#toc').remove();
+  if ($('article h2').length < 2) return;
+  $div_toc = $('<div id="toc"><ul></ul></div>');
+  $div_toc_ul = $div_toc.find('ul');
+  var li_titles = Array();
+  $('article h2').each(function(idx, elem) {
+    var $elem = $(elem);
+    var slug = elem.id;
+    var $a_title = $('<a></a>', {href: '#' + slug, text: $elem.text().replace(/ΒΆ$/, '')});
+    var $li_title = $('<li></li>');
+    $li_title[0].related_position =  $(elem).position().top;
+    li_titles.push($li_title[0]);
+    $a_title.appendTo($li_title);
+    $li_title.appendTo($div_toc_ul);
+  });
+  $('article h1').first().after($div_toc);
+
+  li_titles = li_titles.reverse();
+
+  $(window).on('load', function() {
+    // update positions after images have been loaded
+    $('article h2').each(function(idx, elem) {
+      $('#toc li')[idx].related_position =  $(elem).position().top;
+    });
+    $(window).trigger('scroll');
+  });
+
+  var scroll_timeout_id = null;
+  $(window).on('scroll', function() {
+    if (scroll_timeout_id) clearTimeout(scroll_timeout_id);
+    scroll_timeout_id = setTimeout(function() {  // throttle
+      scroll_timeout_id = null;
+      var current_position = window.scrollY;
+      $('#toc li').removeClass('active');
+      for (const li_title of li_titles) {
+        if (li_title.related_position < current_position - 25) {
+          $(li_title).addClass('active');
+          break;
+        }
+      }
+    }, 50);
+  });
+};
+
 (function(window, document, undefined) {
   var Phylly = {
     BLOCKS: [
@@ -501,6 +546,7 @@ $(function() {
       });
     } else {
       auto_anchors();
+      if ($('main.phyll-toc').length) create_toc();
       Phylly.off(),
       $('button.save').remove();
       $('div[data-editable]').each(function(i, elem) {