From 1c17dbfcee0def48cd0c165ba39b0caff05859ff Mon Sep 17 00:00:00 2001
From: alexisben <alex@noesya.coop>
Date: Tue, 20 Dec 2022 11:36:55 +0100
Subject: [PATCH] toc scrollspy

---
 assets/js/theme/design-system/toc.js        | 45 ++++++++++++++-------
 layouts/partials/ToCamelCase                |  4 ++
 layouts/partials/diplomas/hero-single.html  |  2 +-
 layouts/partials/programs/admission.html    | 16 ++++----
 layouts/partials/programs/hero-single.html  |  2 +-
 layouts/partials/programs/pedagogy.html     | 10 ++---
 layouts/partials/programs/presentation.html |  4 +-
 layouts/partials/programs/results.html      |  6 +--
 layouts/partials/programs/toc.html          | 32 +++++++--------
 9 files changed, 70 insertions(+), 51 deletions(-)
 create mode 100644 layouts/partials/ToCamelCase

diff --git a/assets/js/theme/design-system/toc.js b/assets/js/theme/design-system/toc.js
index c3240f9e..50a9f797 100644
--- a/assets/js/theme/design-system/toc.js
+++ b/assets/js/theme/design-system/toc.js
@@ -4,7 +4,8 @@ const CLASSES = {
   offcanvasOpened: 'has-offcanvas-opened',
   linkActive: 'active',
   isOpened: 'is-opened',
-  fullWidth: 'full-width'
+  fullWidth: 'full-width',
+  offcanvas: 'offcanvas-toc'
 };
 
 class TableOfContents {
@@ -19,7 +20,8 @@ class TableOfContents {
     this.togglers = document.querySelectorAll('.toc-cta button, .toc-container button');
     this.state = {
       opened: false,
-      currentId: null
+      currentId: null,
+      currentLink: 0
     }
     this.listen();
 
@@ -28,7 +30,7 @@ class TableOfContents {
     }
   }
   isOffcanvas() {
-    return isMobile() || document.body.classList.contains(CLASSES.fullWidth);
+    return isMobile() || document.body.classList.contains(CLASSES.fullWidth) || document.body.classList.contains(CLASSES.offcanvas);
   }
   listen() {
     window.addEventListener('scroll', this.update.bind(this), false);
@@ -82,7 +84,7 @@ class TableOfContents {
     const scroll = document.documentElement.scrollTop || document.body.scrollTop;
     let id = null;
     this.sections.forEach(section => {
-      if (this.getAbsoluteOffsetTop(section) <= scroll) {
+      if (this.getAbsoluteOffsetTop(section) <= scroll + window.innerHeight/2) {
         id = section.id;
       }
     });
@@ -93,17 +95,26 @@ class TableOfContents {
     this.updateScrollspy(scroll);
   }
   getAbsoluteOffsetTop(element) {
-    return element.getBoundingClientRect().top
+    let top = 0;
+    do {
+        top += element.offsetTop  || 0;
+        element = element.offsetParent;
+    } while(element);
+    return top
   }
   activateLink(id) {
-    console.log(id)
     const currentLink = this.element.querySelector(`[href*=${ id }]`);
-    this.state.id = id;
-    this.links.forEach(link => link.classList.remove(CLASSES.linkActive));
-    if (currentLink) {
-      currentLink.classList.add(CLASSES.linkActive);
-      this.updateCtaTitle(currentLink);
-    }
+    // console.log(currentLink.hash)
+    this.links.forEach((link, index) => {
+      if (link == currentLink) {
+        link.classList.add(CLASSES.linkActive);
+        this.updateCtaTitle(link);
+        this.state.id = id;
+        this.state.currentLink = link;
+      } else {
+        link.classList.remove(CLASSES.linkActive)
+      }
+    });
   }
   updateCtaTitle(link) {
     if (isMobile()) {
@@ -113,10 +124,14 @@ class TableOfContents {
     }
   }
   updateScrollspy(scroll) {
-    const progression = Math.max((scroll - window.innerHeight) / document.body.offsetHeight, 0);
     const container = this.isOffcanvas() ? this.nav : this.content;
-    // TODO: ne fonctionne pas avec le  behavior-scroll: smooth
-    container.scrollTop = progression * window.innerHeight/2;
+    if (this.state.currentLink) {
+      let progress = (this.getAbsoluteOffsetTop(this.state.currentLink) - container.offsetHeight/2);
+      progress = this.isOffcanvas() ? progress : progress - scroll;
+      container.scrollTo({
+        top: progress
+      })
+    }
   }
 }
 
diff --git a/layouts/partials/ToCamelCase b/layouts/partials/ToCamelCase
new file mode 100644
index 00000000..44702344
--- /dev/null
+++ b/layouts/partials/ToCamelCase
@@ -0,0 +1,4 @@
+{{ $input  := . }}
+{{ $output := $input | lower }}
+{{ $output := $output | markdownify }}
+{{ return $output }}
\ No newline at end of file
diff --git a/layouts/partials/diplomas/hero-single.html b/layouts/partials/diplomas/hero-single.html
index 9f5cb668..69f7b939 100644
--- a/layouts/partials/diplomas/hero-single.html
+++ b/layouts/partials/diplomas/hero-single.html
@@ -24,7 +24,7 @@
       {{ end -}}
     </div>
   </div>
-  <div id="#{{ anchorize (i18n "programs.toc.essential") }}">
+  <div id="#{{ urlize (i18n "programs.toc.essential") }}">
     <div class="container">
       {{- partial "diplomas/essential" . -}}
     </div>
diff --git a/layouts/partials/programs/admission.html b/layouts/partials/programs/admission.html
index 14be0161..50d5ec34 100644
--- a/layouts/partials/programs/admission.html
+++ b/layouts/partials/programs/admission.html
@@ -1,25 +1,25 @@
 {{- if or (partial "GetTextFromHTML" .Params.prerequisites) (partial "GetTextFromHTML" .Params.pricing) (partial "GetTextFromHTML" .Params.registration) (partial "GetTextFromHTML" .Params.accessibility) (partial "GetTextFromHTML" .Params.other) -}}
-<section id="{{ anchorize (i18n "programs.toc.admission") }}">
+<section id="{{ urlize (i18n "programs.toc.admission") }}">
   <div class="container">
     <div class="content">
       <h2>{{ i18n "programs.toc.admission" }}</h2>
       <div>
         {{- if partial "GetTextFromHTML" .Params.prerequisites -}}
-          <section id="{{ anchorize (i18n "programs.prerequisites") }}">
+          <section id="{{ urlize (i18n "programs.prerequisites") }}">
             <h3>{{ i18n "programs.prerequisites" }}</h3>
             {{- partial "PrepareHTML" .Params.prerequisites -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.pricing -}}
-          <section id="{{ anchorize (i18n "programs.pricing") }}">
+          <section id="{{ urlize (i18n "programs.pricing") }}">
             <h3>{{ i18n "programs.pricing" }}</h3>
             {{- partial "PrepareHTML" .Params.pricing -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.registration -}}
-          <section id="{{ anchorize (i18n "programs.registration") }}">
+          <section id="{{ urlize (i18n "programs.registration") }}">
             <h3>{{ i18n "programs.registration" }}</h3>
             {{- partial "PrepareHTML" .Params.registration -}}
             {{- if partial "GetTextFromHTML" .Params.registration_url -}}
@@ -29,21 +29,21 @@
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.accessibility -}}
-          <section id="{{ anchorize (i18n "programs.accessibility") }}">
+          <section id="{{ urlize (i18n "programs.accessibility") }}">
             <h3>{{ i18n "programs.accessibility" }}</h3>
             {{- partial "PrepareHTML" .Params.accessibility -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.other -}}
-          <section id="{{ anchorize (i18n "programs._other") }}">
+          <section id="{{ urlize (i18n "programs._other") }}">
             <h3>{{ i18n "programs._other" }}</h3>
             {{- partial "PrepareHTML" .Params.other -}}
           </section>
         {{- end -}}
 
         {{- if .Params.roles -}}
-          <section id="{{ anchorize (i18n "programs.roles") }}">
+          <section id="{{ urlize (i18n "programs.roles") }}">
             <h3>{{ i18n "programs.roles" }}</h3>
             {{- with .Params.roles -}}
               {{- range . }}
@@ -74,7 +74,7 @@
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.contacts -}}
-          <section id="{{ anchorize (i18n "programs.contacts") }}">
+          <section id="{{ urlize (i18n "programs.contacts") }}">
             <h3>{{ i18n "programs.contacts" }}</h3>
             {{- if or (partial "GetTextFromHTML" .Params.contacts) -}}
               {{- partial "PrepareHTML" .Params.contacts -}}
diff --git a/layouts/partials/programs/hero-single.html b/layouts/partials/programs/hero-single.html
index 4df408f6..bd3de229 100644
--- a/layouts/partials/programs/hero-single.html
+++ b/layouts/partials/programs/hero-single.html
@@ -9,7 +9,7 @@
     </div>
   </div>
 
-  <div id="#{{ anchorize (i18n "programs.toc.essential") }}">
+  <div id="#{{ urlize (i18n "programs.toc.essential") }}">
     <div class="container">
       {{- partial "programs/essential" . -}}
       <div class="buttons">
diff --git a/layouts/partials/programs/pedagogy.html b/layouts/partials/programs/pedagogy.html
index 1b8d7b2f..fbc1bdf4 100644
--- a/layouts/partials/programs/pedagogy.html
+++ b/layouts/partials/programs/pedagogy.html
@@ -1,25 +1,25 @@
 {{- if or (partial "GetTextFromHTML" .Params.content) (partial "GetTextFromHTML" .Params.pedagogy) (partial "GetTextFromHTML" .Params.evaluation) (.Params.teachers) -}}
-<section id="{{ anchorize ( i18n "programs.toc.pedagogy" ) }}">
+<section id="{{ urlize ( i18n "programs.toc.pedagogy" ) }}">
   <div class="container">
     <div class="content">
       <h2>{{ i18n "programs.toc.pedagogy" }}</h2>
       <div>
         {{- if partial "GetTextFromHTML" .Params.content -}}
-          <section id="{{ anchorize (i18n "programs.content") }}">
+          <section id="{{ urlize (i18n "programs.content") }}">
             <h3>{{ i18n "programs.content" }}</h3>
             {{- partial "PrepareHTML" .Params.content -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.pedagogy -}}
-          <section id="{{ anchorize (i18n "programs.pedagogy") }}">
+          <section id="{{ urlize (i18n "programs.pedagogy") }}">
             <h3>{{ i18n "programs.pedagogy" }}</h3>
             {{- partial "PrepareHTML" .Params.pedagogy -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.evaluation -}}
-          <section id="{{ anchorize (i18n "programs.evaluation") }}">
+          <section id="{{ urlize (i18n "programs.evaluation") }}">
             <h3>{{ i18n "programs.evaluation" }}</h3>
             {{- partial "PrepareHTML" .Params.evaluation -}}
           </section>
@@ -27,7 +27,7 @@
 
         {{- if .Params.teachers -}}
           {{ $title := i18n "programs.teachers" -}}
-          <section >
+          <section id="{{ urlize $title }}">
             <h3>{{ $title }}</h3>
             {{- partial "programs/teachers.html"
                           (dict
diff --git a/layouts/partials/programs/presentation.html b/layouts/partials/programs/presentation.html
index a42579a3..ac4b5f03 100644
--- a/layouts/partials/programs/presentation.html
+++ b/layouts/partials/programs/presentation.html
@@ -1,4 +1,4 @@
-<section id="{{ anchorize (i18n "programs.toc.presentation") }}">
+<section id="{{ urlize (i18n "programs.toc.presentation") }}">
     <div class="container">
       <div class="content">
         <h2>{{ i18n "programs.toc.presentation" }}</h2>
@@ -9,7 +9,7 @@
             {{- partial "PrepareHTML" .Params.objectives -}}
           {{- end -}}
 
-          <section id="{{ anchorize (i18n "programs.administrative_information") }}">
+          <section id="{{ urlize (i18n "programs.administrative_information") }}">
             <h3>{{ i18n "programs.administrative_information" }}</h3>
             <table class="post-infos">
               <caption>{{ i18n "programs.administrative_information" }}</caption>
diff --git a/layouts/partials/programs/results.html b/layouts/partials/programs/results.html
index 711759bd..2ebb05da 100644
--- a/layouts/partials/programs/results.html
+++ b/layouts/partials/programs/results.html
@@ -1,18 +1,18 @@
 {{- if or (partial "GetTextFromHTML" .Params.opportunities) (partial "GetTextFromHTML" .Params.results) -}}
-<section id="{{ anchorize ( i18n "programs.toc.results" ) }}">
+<section id="{{ urlize ( i18n "programs.toc.results" ) }}">
   <div class="container">
     <div class="content">
       <h2>{{ i18n "programs.toc.results" }}</h2>
       <div>
         {{- if partial "GetTextFromHTML" .Params.opportunities -}}
-          <section id="{{ anchorize (i18n "programs.opportunities") }}">
+          <section id="{{ urlize (i18n "programs.opportunities") }}">
             <h3>{{ i18n "programs.opportunities" }}</h3>
             {{- partial "PrepareHTML" .Params.opportunities -}}
           </section>
         {{- end -}}
 
         {{- if partial "GetTextFromHTML" .Params.results -}}
-          <section id="{{ anchorize (i18n "programs.results") }}">
+          <section id="{{ urlize (i18n "programs.results") }}">
             <h3>{{ i18n "programs.results" }}</h3>
             {{- partial "PrepareHTML" .Params.results -}}
           </section>
diff --git a/layouts/partials/programs/toc.html b/layouts/partials/programs/toc.html
index 6cdf3caa..8e858cfd 100644
--- a/layouts/partials/programs/toc.html
+++ b/layouts/partials/programs/toc.html
@@ -19,12 +19,12 @@
 <nav class="toc" id="nav-toc" aria-label="{{ i18n "commons.toc" }}">
   <ol>
     <li>
-      <a href="#{{ anchorize (i18n "programs.toc.essential") }}">{{ i18n "programs.toc.essential" }}</a>
+      <a href="#{{ urlize (i18n "programs.toc.essential") }}">{{ i18n "programs.toc.essential" }}</a>
     </li>
     <li>
-      <a href="#{{ anchorize (i18n "programs.toc.presentation") }}">{{ i18n "programs.toc.presentation" }}</a>
+      <a href="#{{ urlize (i18n "programs.toc.presentation") }}">{{ i18n "programs.toc.presentation" }}</a>
        <ol>
-          <li><a href="#{{ anchorize (i18n "programs.administrative_information") }}">{{ i18n "programs.administrative_information" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.administrative_information") }}">{{ i18n "programs.administrative_information" }}</a></li>
           {{- if .context.Params.blocks -}}
             {{- partial "blocks/toc" .context.Params.blocks -}}
           {{- end -}}
@@ -35,16 +35,16 @@
       {{- if or $content $pedagogy $evaluation $teachers }}
       <ol>
         {{- if $content -}}
-          <li><a href="#{{ anchorize (i18n "programs.content") }}">{{ i18n "programs.content" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.content") }}">{{ i18n "programs.content" }}</a></li>
         {{- end -}}
         {{- if $pedagogy -}}
-          <li><a href="#{{ anchorize (i18n "programs.pedagogy") }}">{{ i18n "programs.pedagogy" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.pedagogy") }}">{{ i18n "programs.pedagogy" }}</a></li>
         {{- end -}}
         {{- if $evaluation -}}
-          <li><a href="#{{ anchorize (i18n "programs.evaluation") }}">{{ i18n "programs.evaluation" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.evaluation") }}">{{ i18n "programs.evaluation" }}</a></li>
         {{- end -}}
         {{- if $teachers -}}
-          <li><a href="#{{ anchorize (i18n "programs.teachers") }}">{{ i18n "programs.teachers" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.teachers") }}">{{ i18n "programs.teachers" }}</a></li>
         {{- end -}}
       </ol>
       {{ end -}}
@@ -54,10 +54,10 @@
       {{- if or $opportunities $results }}
       <ol>
         {{- if $opportunities -}}
-          <li><a href="#{{ anchorize (i18n "programs.opportunities") }}">{{ i18n "programs.opportunities" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.opportunities") }}">{{ i18n "programs.opportunities" }}</a></li>
         {{- end -}}
         {{- if $results -}}
-          <li><a href="#{{ anchorize (i18n "programs.results") }}">{{ i18n "programs.results" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.results") }}">{{ i18n "programs.results" }}</a></li>
         {{- end -}}
       </ol>
       {{ end -}}
@@ -67,25 +67,25 @@
       {{- if or $prerequisites $pricing $registration $accessibility $other $roles $contacts }}
       <ol>
         {{- if $prerequisites -}}
-          <li><a href="#{{ anchorize (i18n "programs.prerequisites") }}">{{ i18n "programs.prerequisites" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.prerequisites") }}">{{ i18n "programs.prerequisites" }}</a></li>
         {{- end -}}
         {{- if $pricing -}}
-          <li><a href="#{{ anchorize (i18n "programs.pricing") }}">{{ i18n "programs.pricing" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.pricing") }}">{{ i18n "programs.pricing" }}</a></li>
         {{- end -}}
         {{- if $registration -}}
-          <li><a href="#{{ anchorize (i18n "programs.registration") }}">{{ i18n "programs.registration" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.registration") }}">{{ i18n "programs.registration" }}</a></li>
         {{- end -}}
         {{- if $accessibility -}}
-          <li><a href="#{{ anchorize (i18n "programs.accessibility") }}">{{ i18n "programs.accessibility" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.accessibility") }}">{{ i18n "programs.accessibility" }}</a></li>
         {{- end -}}
         {{- if $other -}}
-          <li><a href="#{{ anchorize (i18n "programs._other") }}">{{ i18n "programs._other" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs._other") }}">{{ i18n "programs._other" }}</a></li>
         {{- end -}}
         {{- if $roles -}}
-          <li><a href="#{{ anchorize (i18n "programs.roles") }}">{{ i18n "programs.roles" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.roles") }}">{{ i18n "programs.roles" }}</a></li>
         {{- end -}}
         {{- if $contacts -}}
-          <li><a href="#{{ anchorize (i18n "programs.contacts") }}">{{ i18n "programs.contacts" }}</a></li>
+          <li><a href="#{{ urlize (i18n "programs.contacts") }}">{{ i18n "programs.contacts" }}</a></li>
         {{- end -}}
       </ol>
       {{ end -}}
-- 
GitLab