From 563d39ff2d75b5575986985b9d1016f99956fb23 Mon Sep 17 00:00:00 2001 From: Marcel Diegelmann Date: Thu, 16 Apr 2026 16:07:35 +0200 Subject: [PATCH] =?UTF-8?q?Turbo-Kompatibilit=C3=A4t=20verbessern.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hinzufügen von Prüfungen auf Vorhandensein von DOM-Elementen in mehreren Controllern sowie Optimierung der Form-Submit-Logik für bessere Turbo-Integration. Anpassung von Template-Elementen und JavaScript-Events zur Unterstützung von Turbo Morphing auf der Startseite. --- .../elements/part_search_controller.js | 16 +++++- .../elements/sidebar_tree_controller.js | 4 ++ .../pages/label_download_btn_controller.js | 7 ++- .../turbo/locale_menu_controller.js | 6 +- assets/js/register_events.js | 36 +++++++++++- templates/base.html.twig | 8 +++ .../components/new_version.macro.html.twig | 4 +- templates/components/search.macro.html.twig | 2 + templates/homepage.html.twig | 56 ++++++++++--------- 9 files changed, 104 insertions(+), 35 deletions(-) diff --git a/assets/controllers/elements/part_search_controller.js b/assets/controllers/elements/part_search_controller.js index 16b4c632..d38a3ad6 100644 --- a/assets/controllers/elements/part_search_controller.js +++ b/assets/controllers/elements/part_search_controller.js @@ -73,6 +73,7 @@ export default class extends Controller { //If the element is in navbar mode, or not const navbar_mode = this.element.dataset.navbarMode === "true"; + const panel_container_element = document.getElementById("navbar-search-form"); const that = this; @@ -124,7 +125,7 @@ export default class extends Controller { query: this.element.dataset.initialQuery || that.inputTarget.value || "" }, //Place the panel in the navbar, if the element is in navbar mode - panelContainer: navbar_mode ? document.getElementById("navbar-search-form") : document.body, + panelContainer: (navbar_mode && panel_container_element) ? panel_container_element : document.body, panelPlacement: this.element.dataset.panelPlacement, plugins: [recentSearchesPlugin], openOnFocus: true, @@ -152,6 +153,11 @@ export default class extends Controller { // If the form is submitted, forward the term to the form onSubmit({ state, event, ...setters }) { + // If the user pressed enter, we want to submit the form + if (event) { + event.preventDefault(); + } + //Put the current text into each target input field const input = that.inputTarget; @@ -167,7 +173,13 @@ export default class extends Controller { input.value = state.query; if (input.form) { - input.form.requestSubmit(); + // We prefer requestSubmit() as it is more compatible with Turbo and triggers submit event listeners + // However, we fallback to submit() if requestSubmit() is not available + if (typeof input.form.requestSubmit === 'function') { + input.form.requestSubmit(); + } else { + input.form.submit(); + } } }, diff --git a/assets/controllers/elements/sidebar_tree_controller.js b/assets/controllers/elements/sidebar_tree_controller.js index d50cf900..078e8e05 100644 --- a/assets/controllers/elements/sidebar_tree_controller.js +++ b/assets/controllers/elements/sidebar_tree_controller.js @@ -60,6 +60,10 @@ export default class extends TreeController { doUpdateIfNeeded() { const info_element = document.getElementById('sidebar-last-time-updated'); + if (!info_element) { + return; + } + const date_str = info_element.dataset.lastUpdate; const server_last_update = new Date(date_str); diff --git a/assets/controllers/pages/label_download_btn_controller.js b/assets/controllers/pages/label_download_btn_controller.js index 01c0ba10..698d80f4 100644 --- a/assets/controllers/pages/label_download_btn_controller.js +++ b/assets/controllers/pages/label_download_btn_controller.js @@ -22,6 +22,9 @@ import {Controller} from "@hotwired/stimulus"; export default class extends Controller { download(event) { - this.element.href = document.getElementById('pdf_preview').data + const preview = document.getElementById('pdf_preview'); + if (preview) { + this.element.href = preview.data; + } } -} \ No newline at end of file +} diff --git a/assets/controllers/turbo/locale_menu_controller.js b/assets/controllers/turbo/locale_menu_controller.js index d55ff8da..54f7dc0c 100644 --- a/assets/controllers/turbo/locale_menu_controller.js +++ b/assets/controllers/turbo/locale_menu_controller.js @@ -22,6 +22,8 @@ import { Controller } from '@hotwired/stimulus'; export default class extends Controller { connect() { const menu = document.getElementById('locale-select-menu'); - menu.innerHTML = this.element.innerHTML; + if (menu) { + menu.innerHTML = this.element.innerHTML; + } } -} \ No newline at end of file +} diff --git a/assets/js/register_events.js b/assets/js/register_events.js index 9732c0c1..27c7d626 100644 --- a/assets/js/register_events.js +++ b/assets/js/register_events.js @@ -35,6 +35,7 @@ class RegisterEventHelper { }); this.registerModalDropRemovalOnFormSubmit(); + this.registerHomepageCleanupOnSearch(); } @@ -63,6 +64,39 @@ class RegisterEventHelper { document.addEventListener('turbo:load', fn); } + registerHomepageCleanupOnSearch() { + const cleanup = () => { + const ids = [ + 'homepage-banner-container', + 'homepage-last-activity-container', + 'homepage-search-container', + 'homepage-first-steps', + 'homepage-license', + 'new-version-alert' + ]; + + const isSearchPage = window.location.pathname.includes('/search') || window.location.search.includes('keyword='); + + ids.forEach(id => { + const elements = document.querySelectorAll('#' + id); + elements.forEach(el => { + if (isSearchPage) { + //We hide it, instead of removing it, to not break Turbo Morphing anchors + el.style.setProperty('display', 'none', 'important'); + } else { + //On non-search pages, we ensure it is visible again if it was hidden by this script + //But only if it's not one of the "anchor" divs from base.html.twig which should stay hidden + if (el.hasAttribute('data-turbo-temporary')) { + el.style.display = ''; + } + } + }); + }); + }; + + this.registerLoadHandler(cleanup); + } + configureDropdowns() { this.registerLoadHandler(() => { //Set the dropdown strategy to fixed, so that the dropdowns are not cut off by the overflow: hidden of the body. @@ -328,4 +362,4 @@ class RegisterEventHelper { } } -export default new RegisterEventHelper(); \ No newline at end of file +export default new RegisterEventHelper(); diff --git a/templates/base.html.twig b/templates/base.html.twig index 2db726ee..62fbee53 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -95,6 +95,14 @@ {# Here will be the real content be injected#} + {# These empty divs are here to ensure that Turbo Morphing correctly removes homepage elements when navigating away #} +
+
+
+
+
+
+ {% block content %} {% endblock %} diff --git a/templates/components/new_version.macro.html.twig b/templates/components/new_version.macro.html.twig index f8bc1e2e..2b8294d6 100644 --- a/templates/components/new_version.macro.html.twig +++ b/templates/components/new_version.macro.html.twig @@ -1,9 +1,9 @@ {% macro new_version_alert(is_available, new_version, new_version_url) %} {% if is_available %} - {# And right in the standalone mode #} diff --git a/templates/homepage.html.twig b/templates/homepage.html.twig index 6e7aa360..cf919995 100644 --- a/templates/homepage.html.twig +++ b/templates/homepage.html.twig @@ -6,33 +6,37 @@ {% block item_search %} {% if is_granted('@parts.read') %} - {{ search.search_form("standalone") }} +
+ {{ search.search_form("standalone") }} +
{% endif %} {% endblock %} {% block item_banner %} -
-

{{ vars.partdb_title() }}

- {% if settings_instance('customization').showVersionOnHomepage %} -

- {% trans %}version.caption{% endtrans %}: {{ shivas_app_version }} - {% if git_branch is not empty or git_commit is not empty %} - ({{ git_branch ?? '' }}/{{ git_commit ?? '' }}) - {% endif %} -

- {% endif %} - {% if banner is not empty %} -
-
-
{{ banner | format_markdown }}
-
- {% endif %} +
+
+

{{ vars.partdb_title() }}

+ {% if settings_instance('customization').showVersionOnHomepage %} +

+ {% trans %}version.caption{% endtrans %}: {{ shivas_app_version }} + {% if git_branch is not empty or git_commit is not empty %} + ({{ git_branch ?? '' }}/{{ git_commit ?? '' }}) + {% endif %} +

+ {% endif %} + {% if banner is not empty %} +
+
+
{{ banner | format_markdown }}
+
+ {% endif %} +
{% endblock %} {% block item_first_steps %} {% if show_first_steps %} -
+

{% trans %}homepage.first_steps.title{% endtrans %}

@@ -53,7 +57,7 @@ {% endblock %} {% block item_license %} -
+

{% trans %}homepage.license{% endtrans %}

@@ -73,18 +77,19 @@ {% block item_last_activity %} {% if datatable is not null %} -
-
{% trans %}homepage.last_activity{% endtrans %}
-
- {% import "components/history_log_macros.html.twig" as log %} - {{ log.last_activity_component(datatable) }} +
+
+
{% trans %}homepage.last_activity{% endtrans %}
+
+ {% import "components/history_log_macros.html.twig" as log %} + {{ log.last_activity_component(datatable) }} +
{% endif %} {% endblock %} {% block content %} - {% if is_granted('@system.show_updates') %} {{ nv.new_version_alert(new_version_available, new_version, new_version_url) }} {% endif %} @@ -99,5 +104,4 @@
{% endif %} {% endfor %} - {% endblock %}