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