From 08395d5eafc2ee76da13dad2859bc478b6ea1129 Mon Sep 17 00:00:00 2001 From: Max P Date: Thu, 30 Nov 2023 18:09:39 +0100 Subject: [PATCH 1/4] The option to set a configurable show/hide button has been added. Changes - Configuration: - toggle Activate the button or not. - initially_hide Hidden in initial state or not. - hide_text The text of the button to hide the menu. - show_text The text of the button to make the menu visible. - CSS: Corresponding classes created for the button (with ID) and for hiding or making visible. - PHP: Added logic to add the button. This also works without a heading text being set. --- TableOfContents.php | 43 ++++++++++++++++++++++++++++++++++++++----- js/toc.js | 21 +++++++++++++++++++++ style.css | 21 +++++++++++++++++++-- 3 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 js/toc.js diff --git a/TableOfContents.php b/TableOfContents.php index 1fc5f2c..40b90d5 100644 --- a/TableOfContents.php +++ b/TableOfContents.php @@ -23,9 +23,17 @@ class TableOfContents extends AbstractPicoPlugin 'style' => 'none', // Heading text, if a heading for the table of contents is desired. 'heading' => null, + // Show/hide the table of contents by default. + 'toggle' => true, + // Hide toc initially + 'initially_hide' => true, + // Hide text + 'hide_text' => '▲', + // Show text + 'show_text' => '▼', ); - protected $min_headers, $min_level, $max_level, $tag, $style, $heading, $toc_element_xml; + protected $min_headers, $min_level, $max_level, $tag, $style, $toggle, $initially_hide, $hide_text, $show_text, $heading, $toc_element_xml; protected $available_tags = ['ol', 'ul']; protected $available_styles = ['numbers', 'bullets', 'none', 'default']; @@ -90,6 +98,10 @@ public function onMetaParsed(array &$meta) $this->tag = $this->getVal('tag', $meta); $this->style = $this->getVal('style', $meta); $this->heading = $this->getVal('heading', $meta); + $this->initially_hide = $this->getVal('initially_hide', $meta); + $this->toggle = $this->getVal('toggle', $meta); + $this->hide_text = $this->getVal('hide_text', $meta); + $this->show_text = $this->getVal('show_text', $meta); // Check if the tag is valid if (!in_array($this->tag, $this->available_tags)) { @@ -147,9 +159,21 @@ public function onContentParsed(&$content) $div_element->setAttribute('id', 'toc'); // Add heading element, if enabled - if (isset($this->heading)) { - $heading_element = $document->createElement('div', $this->heading); + if (isset($this->heading) || $this->toggle) { + $heading_element = $document->createElement('div', isset($this->heading) ? $this->heading : ' '); $heading_element->setAttribute('class', 'toc-heading'); + + // Create the toogle button element if enabled + if($this->toggle) + { + $button_element = $document->createElement('button', $this->initially_hide ? $this->show_text : $this->hide_text); + $button_element->setAttribute('id', 'toc-toggle'); + $button_element->setAttribute('data-show-text', $this->show_text); + $button_element->setAttribute('data-hide-text', $this->hide_text); + + $heading_element->appendChild($button_element); + } + $div_element->appendChild($heading_element); } @@ -208,7 +232,7 @@ private function getVal($key, $meta) * @param integer $index * @return DOMElement */ - private function getList($document, $headers, &$index = 0) + private function getList($document, $headers, &$index = 0, $isTopLevel = true) { // Initialize ordered list element $list_element = $document->createElement($this->tag); @@ -216,6 +240,15 @@ private function getList($document, $headers, &$index = 0) $list_element->setAttribute('class', "toc-$this->style"); } + if ($this->toggle && $isTopLevel) + { + if ($this->initially_hide === true) { + $list_element->setAttribute('class', 'toc-hide'); + } else { + $list_element->setAttribute('class', 'toc-show'); + } + } + for ($index; $index < $headers->length; $index++) { $curr_header = $headers[$index]; if (isset($curr_header->tagName) && $curr_header->tagName !== '') { @@ -237,7 +270,7 @@ private function getList($document, $headers, &$index = 0) if ($next_header && strtolower($curr_header->tagName) < strtolower($next_header->tagName)) { // The next header is at a lower level -> add nested headers $index++; - $nested_list_element = $this->getList($document, $headers, $index); + $nested_list_element = $this->getList($document, $headers, $index, false); $li_element->appendChild($nested_list_element); } diff --git a/js/toc.js b/js/toc.js new file mode 100644 index 0000000..2f50186 --- /dev/null +++ b/js/toc.js @@ -0,0 +1,21 @@ +var toggleTocElement = document.getElementById("toc-toggle"); + +if (toggleTocElement) { + toggleTocElement.addEventListener("click", function() { + var tocElement = document.getElementById("toc"); + if (tocElement) { + var xElement = tocElement.querySelector(".toc-hide, .toc-show"); + if (xElement) { + if (xElement.classList.contains("toc-hide")) { + xElement.classList.remove("toc-hide"); + xElement.classList.add("toc-show"); + this.innerText = this.getAttribute('data-show-text'); + } else if (xElement.classList.contains("toc-show")) { + xElement.classList.remove("toc-show"); + xElement.classList.add("toc-hide"); + this.innerText = this.getAttribute('data-hide-text'); + } + } + } + }); +} diff --git a/style.css b/style.css index 52e2206..00d67a5 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,7 @@ #toc { border : 1px solid #cdd; background-color: #f5f5ff; - margin : 0; + margin : 20px 0 20px 0; padding : 1em; font-size : 80%; } @@ -29,7 +29,7 @@ .toc-numbers { counter-reset : item; - list-style-type: none; + list-style-type: none; } .toc-numbers li:before { content : counters(item, ". ") ". "; @@ -39,4 +39,21 @@ .toc-heading { font-size : larger; font-weight: bold; + position: relative; +} + +#toc-toggle { + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + /* Weitere Stiloptionen nach Wunsch */ } + +.toc-hide { + display: none; +} + +.toc-show { + display: inherit; +} \ No newline at end of file From 3fb736bf4eb0991d19e12521f802be30229fba97 Mon Sep 17 00:00:00 2001 From: Max P Date: Thu, 30 Nov 2023 19:17:33 +0100 Subject: [PATCH 2/4] Adjusted the README.md file to the possibility to hide and show the ToC with a configurable button. --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index c45d1a1..bcd801c 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ plugins └───TableOfContents │ style.css │ TableOfContents.php + └───js + | toc.js ``` Pico Table Of Contents plugin requires PHP >=7.0. @@ -70,6 +72,11 @@ In your template files, add a link to the plugin stylesheet in the `head` sectio ... +... +... + + + ``` @@ -88,6 +95,10 @@ You can change the default configuration by adding values to your `config` file. * **none** (no item marker is shown) * **default** (the default css style applied to lists) * `heading` - Heading text, if a heading for the ToC is desired. - *Default value: (unset)* +* `toggle` - Activate the Show/Hide button or not. - *Default value: (true)* +* `initially_hide` - Hidden ToC in initial state or not. - *Default value: (true)* +* `hide_text` - The text of the button to hide the menu. - *Default value: (▲)* +* `hide_text` - The text of the button to make the menu visible. - *Default value: (▼)* For reference, these values are set in `config/config.yml` using the following format: @@ -102,6 +113,10 @@ TOC: tag: ol style: none heading: Contents + toggle: true + initially_hide: true + hide_text: ▲ + show_text: ▼ ``` This configuration will be applied to the entire site, but it's also possible to override it for a specific page by adding the Meta headers with the same format (see the [example](#example)). From 490c212ebff0d60ef95e2e65ed9cdd722e9d74b7 Mon Sep 17 00:00:00 2001 From: Max P Date: Thu, 30 Nov 2023 20:15:52 +0100 Subject: [PATCH 3/4] Removed a logic error in JavaScript. The show/hide symbols are now displayed at the correct time. --- js/toc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/toc.js b/js/toc.js index 2f50186..9d7f99e 100644 --- a/js/toc.js +++ b/js/toc.js @@ -9,11 +9,11 @@ if (toggleTocElement) { if (xElement.classList.contains("toc-hide")) { xElement.classList.remove("toc-hide"); xElement.classList.add("toc-show"); - this.innerText = this.getAttribute('data-show-text'); + this.innerText = this.getAttribute('data-hide-text'); } else if (xElement.classList.contains("toc-show")) { xElement.classList.remove("toc-show"); xElement.classList.add("toc-hide"); - this.innerText = this.getAttribute('data-hide-text'); + this.innerText = this.getAttribute('data-show-text'); } } } From 9b660bfde66aa5b57fc509320c88835831b5e295 Mon Sep 17 00:00:00 2001 From: Max P Date: Tue, 19 Dec 2023 14:21:59 +0100 Subject: [PATCH 4/4] - Resolved an issue where the top element was only assigned the toc-* class, which led to the overwriting of the toc-$this->style class. - Adjusted logic to ensure both toc-* and toc-$this->style classes are correctly applied to the top element. --- TableOfContents.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/TableOfContents.php b/TableOfContents.php index 40b90d5..b7e497a 100644 --- a/TableOfContents.php +++ b/TableOfContents.php @@ -240,14 +240,13 @@ private function getList($document, $headers, &$index = 0, $isTopLevel = true) $list_element->setAttribute('class', "toc-$this->style"); } - if ($this->toggle && $isTopLevel) - { - if ($this->initially_hide === true) { - $list_element->setAttribute('class', 'toc-hide'); - } else { - $list_element->setAttribute('class', 'toc-show'); - } - } + if ($this->toggle && $isTopLevel) { + $currentClass = $list_element->getAttribute('class'); + $additionalClass = $this->initially_hide ? 'toc-hide' : 'toc-show'; + + $newClass = $currentClass . ($currentClass ? ' ' : '') . $additionalClass; + $list_element->setAttribute('class', $newClass); + } for ($index; $index < $headers->length; $index++) { $curr_header = $headers[$index];