Fix link-once and script-once not triggering when another one disappears

This commit is contained in:
2026-03-26 23:48:38 +01:00
parent 182cdbe590
commit 3bc4f1300e
4 changed files with 48 additions and 23 deletions

View File

@@ -1,11 +1,7 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link, select_all_checkbox %} {% from 'core/macros.jinja' import user_profile_link, select_all_checkbox %}
{% block additional_js %}
<script type="module" src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script>
{% endblock %}
{% block additional_css %} {% block additional_css %}
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.css") }}">
<link rel="stylesheet" href="{{ static("club/members.scss") }}"> <link rel="stylesheet" href="{{ static("club/members.scss") }}">
{% endblock %} {% endblock %}

View File

@@ -6,14 +6,36 @@ import { inheritHtmlElement, registerComponent } from "#core:utils/web-component
**/ **/
@registerComponent("link-once") @registerComponent("link-once")
export class LinkOnce extends inheritHtmlElement("link") { export class LinkOnce extends inheritHtmlElement("link") {
connectedCallback() { refresh() {
super.connectedCallback(false); this.clearNode();
// We get href from node.attributes instead of node.href to avoid getting the domain part // We get href from node.attributes instead of node.href to avoid getting the domain part
const href = this.node.attributes.getNamedItem("href").nodeValue; const href = this.node.attributes.getNamedItem("href").nodeValue;
if (document.querySelectorAll(`link[href='${href}']`).length === 0) { if (document.querySelectorAll(`link[href='${href}']`).length === 0) {
this.appendChild(this.node); this.appendChild(this.node);
} }
} }
clearNode() {
while (this.firstChild) {
this.removeChild(this.lastChild);
}
}
connectedCallback() {
super.connectedCallback(false);
this.refresh();
}
disconnectedCallback() {
this.clearNode();
// This re-triggers link-once elements that still exists and suppressed
// themeselves once it gets removed from the page
for (const link of document.getElementsByTagName("link-once")) {
(link as LinkOnce).refresh();
}
}
} }
/** /**
@@ -22,12 +44,34 @@ export class LinkOnce extends inheritHtmlElement("link") {
**/ **/
@registerComponent("script-once") @registerComponent("script-once")
export class ScriptOnce extends inheritHtmlElement("script") { export class ScriptOnce extends inheritHtmlElement("script") {
connectedCallback() { refresh() {
super.connectedCallback(false); this.clearNode();
// We get src from node.attributes instead of node.src to avoid getting the domain part // We get src from node.attributes instead of node.src to avoid getting the domain part
const src = this.node.attributes.getNamedItem("src").nodeValue; const src = this.node.attributes.getNamedItem("src").nodeValue;
if (document.querySelectorAll(`script[src='${src}']`).length === 0) { if (document.querySelectorAll(`script[src='${src}']`).length === 0) {
this.appendChild(this.node); this.appendChild(this.node);
} }
} }
clearNode() {
while (this.firstChild) {
this.removeChild(this.lastChild);
}
}
connectedCallback() {
super.connectedCallback(false);
this.refresh();
}
disconnectedCallback() {
this.clearNode();
// This re-triggers script-once elements that still exists and suppressed
// themeselves once it gets removed from the page
for (const link of document.getElementsByTagName("script-once")) {
(link as LinkOnce).refresh();
}
}
} }

View File

@@ -1,14 +1,7 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{%- block additional_js -%}
<script type="module" src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script>
{%- endblock -%}
{%- block additional_css -%} {%- block additional_css -%}
<link rel="stylesheet" href="{{ static('user/user_preferences.scss') }}"> <link rel="stylesheet" href="{{ static('user/user_preferences.scss') }}">
{# importing ajax-select-index is necessary for it to be applied after HTMX reload #}
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.css") }}">
<link rel="stylesheet" href="{{ static("core/components/ajax-select.scss") }}">
{%- endblock -%} {%- endblock -%}
{% block title %} {% block title %}

View File

@@ -6,14 +6,8 @@
{% trans %}New subscription{% endtrans %} {% trans %}New subscription{% endtrans %}
{% endblock %} {% endblock %}
{# The following statics are bundled with our autocomplete select.
However, if one tries to swap a form by another, then the urls in script-once
and link-once disappear.
So we give them here.
If the aforementioned bug is resolved, you can remove this. #}
{% block additional_js %} {% block additional_js %}
<script type="module" src="{{ static('bundled/core/components/tabs-index.ts') }}"></script> <script type="module" src="{{ static('bundled/core/components/tabs-index.ts') }}"></script>
<script type="module" src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script>
<script <script
type="module" type="module"
src="{{ static("bundled/subscription/creation-form-existing-user-index.ts") }}" src="{{ static("bundled/subscription/creation-form-existing-user-index.ts") }}"
@@ -21,8 +15,6 @@
{% endblock %} {% endblock %}
{% block additional_css %} {% block additional_css %}
<link rel="stylesheet" href="{{ static("core/components/tabs.scss") }}"> <link rel="stylesheet" href="{{ static("core/components/tabs.scss") }}">
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.css") }}">
<link rel="stylesheet" href="{{ static("core/components/ajax-select.scss") }}">
<link rel="stylesheet" href="{{ static("subscription/css/subscription.scss") }}"> <link rel="stylesheet" href="{{ static("subscription/css/subscription.scss") }}">
{% endblock %} {% endblock %}