]> git.ipfire.org Git - ipfire.org.git/commitdiff
docs: Make image clickable to zoom in
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Dec 2023 12:21:55 +0000 (12:21 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Dec 2023 12:21:55 +0000 (12:21 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/backend/wiki.py
src/sass/main.sass
src/static/js/site.js

index d2a0b71dbe17cb4f7e571fb1ea5775339eda0d3c..cc5964d14a693e3633d3b65ebfbfb731958f0336 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/python3
 
 import difflib
+import hashlib
 import logging
 import os.path
 import re
@@ -620,20 +621,44 @@ class WikiRenderer(misc.Object):
        def _render_image(self, m):
                alt_text, url, caption = m.groups()
 
+               # Compute a hash over the URL
+               h = hashlib.new("md5")
+               h.update(url.encode())
+               id = h.hexdigest()
+
                html = """
                        <div class="columns is-centered">
                                <div class="column is-8">
-                                       <figure class="image">
-                                               <img src="/docs%s" alt="%s">
-                                               <figcaption class="figure-caption">%s</figcaption>
+                                       <figure class="image modal-trigger" data-target="%(id)s">
+                                               <img src="/docs%(url)s" alt="%(caption)s">
+
+                                               <figcaption class="figure-caption">%(caption)s</figcaption>
                                        </figure>
+
+                                       <div class="modal is-large" id="%(id)s">
+                                               <div class="modal-background"></div>
+
+                                               <div class="modal-content">
+                                                       <p class="image">
+                                                               <img src="/docs%(plain_url)s?s=1920" alt="%(caption)s"
+                                                                       loading="lazy">
+                                                       </p>
+                                               </div>
+
+                                               <button class="modal-close is-large" aria-label="close"></button>
+                                       </div>
                                </div>
                        </div>
                """
 
                # Skip any absolute and external URLs
                if url.startswith("/") or url.startswith("https://") or url.startswith("http://"):
-                       return html % (url, alt_text, caption or "")
+                       return html % {
+                               "caption"   : caption or "",
+                               "id"        : id,
+                               "plain_url" : url,
+                               "url"       : url,
+                       }
 
                # Try to split query string
                url, delimiter, qs = url.partition("?")
@@ -642,7 +667,7 @@ class WikiRenderer(misc.Object):
                args = urllib.parse.parse_qs(qs)
 
                # Build absolute path
-               url = self.backend.wiki.make_path(self.path, url)
+               plain_url = url = self.backend.wiki.make_path(self.path, url)
 
                # Find image
                file = self.backend.wiki.get_file_by_path(url)
@@ -657,7 +682,12 @@ class WikiRenderer(misc.Object):
                if args:
                        url = "%s?%s" % (url, urllib.parse.urlencode(args))
 
-               return html % (url, caption, caption or "")
+               return html % {
+                       "caption"   : caption or "",
+                       "id"        : id,
+                       "plain_url" : plain_url,
+                       "url"       : url,
+               }
 
        def render(self, text):
                logging.debug("Rendering %s" % self.path)
index 735b8ddb584eae2ce4b43038d98b9bc5795876df..9a78cbf2a3e49833870959ccf0caad0ce13e8f67 100644 (file)
@@ -110,6 +110,13 @@ html, body
                &:hover
                        color: $black
 
+.modal
+       &.is-large
+               .modal-content
+                       +from($modal-breakpoint)
+                               width: $widescreen
+                               max-height: 100%
+
 // Used to wrap text on buttons
 .wrap-text
     height: max-content;
index ab6e1f95bce3492679e4ac27cbed7550c6fa0c11..304ee96e6eba0190ec6c8953b10d4c301d221374 100644 (file)
@@ -49,4 +49,47 @@ document.addEventListener('keydown', function(e) {
        if (event.key === 'Esc' || event.key === 'Escape') {\r
                closeDropdowns();\r
        }\r
-});
\ No newline at end of file
+});\r
+\r
+// Modals\r
+document.addEventListener("DOMContentLoaded", () => {\r
+       function openModal($el) {\r
+               $el.classList.add("is-active");\r
+       }\r
+\r
+       function closeModal($el) {\r
+               $el.classList.remove("is-active");\r
+       }\r
+\r
+       function closeAllModals() {\r
+               (document.querySelectorAll(".modal") || []).forEach(($modal) => {\r
+                       closeModal($modal);\r
+               });\r
+       }\r
+\r
+       // Add a click event on buttons to open a specific modal\r
+       (document.querySelectorAll(".modal-trigger") || []).forEach(($trigger) => {\r
+               const modal = $trigger.dataset.target;\r
+               const $target = document.getElementById(modal);\r
+\r
+               $trigger.addEventListener("click", () => {\r
+                       openModal($target);\r
+               });\r
+       });\r
+\r
+       // Add a click event on various child elements to close the parent modal\r
+       (document.querySelectorAll(".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button") || []).forEach(($close) => {\r
+               const $target = $close.closest(".modal");\r
+\r
+               $close.addEventListener("click", (e) => {\r
+                       closeModal($target);\r
+               });\r
+       });\r
+\r
+       // Add a keyboard event to close all modals\r
+       document.addEventListener("keydown", (event) => {\r
+               if (event.code === "Escape") {\r
+                       closeAllModals();\r
+               }\r
+       });\r
+});\r