Ergebnis 1 bis 7 von 7

Thema: JavaScript im Ajax-Backend

  1. #1
    Contao-Nutzer
    Registriert seit
    10.10.2013.
    Beiträge
    71

    Standard JavaScript im Ajax-Backend

    Mit der Umstellung des Backends vom kompletten Seitenload auf Ajax-Reloads werden in der Anzeige keine in z.B. XLabel eingebundene JavaScripts <script></script> oder <script src="xxx.js"></script> mehr ausgeführt, wobei ein referenziertes, externes Scripte laut F12-Netzwerkanalyse sogar geladen wird. Lädt man die Seite manuell nach, funktioniert es natürlich und es wird normal ausgeführt.

    Gibt es irgendeinen Event, den Contao ggf. selbst erzeugt und in den man sich einhängen kann, oder eine andere Möglichkeit, dass eigene Scripte auch bei den Ajax-Reloads gestartet werden können?

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    38.626
    Partner-ID
    10107

    Standard

    Zitat Zitat von 462 Beitrag anzeigen
    werden in der Anzeige keine in z.B. XLabel
    Was genau meinst du mit XLabel?


    Zitat Zitat von 462 Beitrag anzeigen
    <script></script> oder <script src="xxx.js"></script> mehr ausgeführt
    Wie genau hast du diese JavaScripts eingebunden?

    Grundsätzlich ist es so, dass mit Turbo nur der <body> Replaced wird (oder tlw. auch nur <turbo-frame>s). Dein JavaScript muss daher mit dynamisch nachgeladenen Inhalt klar kommen (Stichwort Mutation Observer oder Stimulus). Dein JavaScript muss außerdem entweder Global im <head> geladen sein, über $GLOBALS['TL_JAVASCRIPT'] (wodurch es automatisch einen Refresh geben wird) oder im <body> mit <script>.
    » sponsor me via GitHub or Revolut

  3. #3
    Contao-Nutzer
    Registriert seit
    10.10.2013.
    Beiträge
    71

    Standard

    Mit dem XLabel Callback kann man noch eigene Informationen in das Label der Eingabe eines Tabellenfeldes hinzufügen. Hier kann ja (fast) beliebiges HTML und unter anderem <script>-Tags eingebunden werden, mit dem ich zum Beispiel zusätzliche Informationen aus dem aktuell eingegebenen Text auf der Tabelleneingabeseite erzeuge.

    Dafür ist das zwar wahrscheinlich eigentlich nicht vorgesehen (da es ja an das Ende in ein <h3> eingebaut wird), funktionierte aber inklusive einem Hinzufügen eines EventListener auf DOMContentLoaded im "alten" Backend prima, da das DOM insgesamt neu geladen wurde.

    Im "neuen" Backend wird aber per Ajax eben nur ein Teil der Seite nachgeladen und irgendwo in ein innerHTML geschrieben und somit werden, wie normal üblich, weder ein nachgeladenes Inline-Script noch eine durch das Nachladen referenzierte js-Datei ausgeführt. Zusätzlich gibt es auch kein DOMContentLoaded mehr (was man durch einen MutationsObserver wiederum ersetzen kann).

    Letztendlich ist es erst mal egal, wo das <script> steht. Die Funktion darin muss mit dem Nachladen gestartet werden.

    Die Lösung wäre wohl nur ein MutationObserver, der den <body> auf das Ändern des kompletten DOM überwacht. Der Observer müsste ja dann aber immer global das komplette BE überwachen, falls mal irgendwann was entsprechendes nachgeladen wird. Ist irgendwie nicht wirklich elegant.

    Je länger ich so darüber nachdenke, gibt es aktuell wohl keine wirkliche Möglichkeit, ausschließlich aus dem nachgeladenen Teil <script>-Funktionalitäten selbst zu starten ohne zuvor den ladenden Teil angefasst zu haben. Selbst wenn es einen zentralen Event geben würde, dass etwas nachgeladen wurde, könnte der EventListener darauf ja nicht im nachgeladenen Teil gesetzt werden.

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    38.626
    Partner-ID
    10107

    Standard

    Nachgeladene <script>s werden wie gesagt ausgeführt.

    Den MutationObserver machst du nicht am <body>, sondern auf den Elementen, die dich interessieren.
    » sponsor me via GitHub or Revolut

  5. #5
    Contao-Nutzer
    Registriert seit
    10.10.2013.
    Beiträge
    71

    Standard

    Super. Es funktioniert, auch wenn man eben ein globales Script braucht, da ja dem nichtnachgeladenen Backend-Rahmen nicht bekannt ist, was alles so nachgeladen werden könnte. Alternativ müsste man nachgeladene Scripte nach dem Laden aktiv "restarten".

    Und es funktioniert sowohl für das "alte" als auch das "neue" Backend.


    Ich denke, dies ist aber nun die bessere/sauberere Lösung:

    1. Im XLabel Callback baue ich ein Daten-Element ein (nicht mehr das Script selbst), was die Variablen an das zentrale Javascript übergibt und nebenbei als Kenner fungiert, dass hier was "Eigenes" vorhanden ist.
    Code:
    return <<<EOT
        <span id="myapp-callback1-data" class="myapp-data"
            data-myvalue="$myValue"
            data-myimage='$myImage'>
        </span>
        EOT;
    Dabei ist darauf zu achten, dass das Dataset im Javascript nachher die Benennung ausschließlich in Kleinbuchstaben ausführt: dataspan.dataset.data-myvalue. Auch die Anführungszeichen sind zu beachten, da $myImage hier als HTML mit ""-Eigenschaften ausgeführt ist.


    2. Es gibt ein zentrales Javascript, was insbesondere das grundlegende Event-Handling und praktikablerweise auch die Callback(s) ausführt:
    Code:
    (function() {
        document.addEventListener('DOMContentLoaded', () => {
            document.addEventListener('myapp:loaded', () => {
                if (document.querySelector('.myapp-data')) {
                    MyCallback1();
                    // ...
                }
            });
    
            const e = new CustomEvent('myapp:loaded');
    
            if (window.Turbo) {
                document.addEventListener('turbo:load', () => {
                    document.dispatchEvent(e);
                })
            }
            document.dispatchEvent(e);
        });
    
        function MyCallback1() {
            //...
        }
    
        // ...
    })()
    Das Nachladen von Komponenten im Backend erfolgt über den Frame-Handler Turbo. Der Bereich mit dem Tag <turbo-frame> wird bei jedem Seitenwechsel aktualisiert.

    Der Abschluss des Nachladen eines Frames wird durch das Event turbo:load angezeigt. Die Prüfung, ob Turbo vorhanden ist könnte gegebenenfalls auch entfallen. Andere Event-Handler von Turbo sind nicht erforderlich. Normale MutationObserver auf <body> oder <turbo-frame> funktionieren gar nicht oder nur beim ersten Nachladen.


    3. Das zentrale Javascript wird beispielsweise in der config/config.php der Erweiterung eingebunden.
    Code:
    $GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myapp/be.js';
    Ein Einbinden in den Javascript-Bereich der Erweiterung ($GLOBALS['BE_MOD']['content']['myapp'] = ['javascript' => ...]) funktioniert nicht, da das Javascript dann nur aufgerufen wird, wenn die Seite der Erweiterung selbst beim ersten Laden des Backends die aktive Seite ist. Startet man mit einer anderen Backend-Seite und wechselt dann auf die Seite der Erweiterung, wird ja nur deren Frame-Inhalt nachgeladen und das Javascript der Erweiterung selbst verbleibt unberücksichtigt.

  6. #6
    Contao-Urgestein
    Registriert seit
    24.02.2021.
    Beiträge
    2.061
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Zitat Zitat von 462 Beitrag anzeigen
    Alternativ müsste man nachgeladene Scripte nach dem Laden aktiv "restarten".
    Mit MutationObservern geht das, dann spart man sich das ganze CustomEvent Rum-ge-hacke.

    Edit (für mehr Infos für dich): Mit MutationObserver (wie von Spooky erwähnt) überprüfen ob das Dom-Element auftaucht, dann das Skript initialisieren.

    Edit (2): Was du programmiert hast, lässt sich komplett durch einen MutationObserver ersetzen. Nix CustomEvent mit Apploaded und Turbo Bingo notwendig.

  7. #7
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    38.626
    Partner-ID
    10107

    Standard

    Ja, wie gesagt solltest du das lieber über MutationObserver machen, dann können dir die Events egal sein.
    » sponsor me via GitHub or Revolut

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 16 (Registrierte Benutzer: 0, Gäste: 16)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •