Linuchs: In welcher Reihenfolge werden DOMContentLoaded abgearbeitet?

problematische Seite

Moin,

für Liedtexte mit Audio- und Videospuren lade ich mehrere .js Dateien

  <script src="../css/formatiert_a3_a5_a6.js"></script><!-- *.htm?a6 -->
  <script src="../css/setze_seitenzahlen.js"></script><!-- *.htm?a6Nr.04 -->
  <script src="../css/lied_mehrspurig.js"></script>
  <script src="../css/tempo_handler.js"></script>
  <script src="../css/setze_akkorde.js"></script>

und jede enthält

window.addEventListener('DOMContentLoaded', function () {
...
}

Wenn die Akkorde gesetzt werden, wird in lied_mehrspurig die Lautstärke NICHT verringert.

Da ich keine Idee habe, ob diese Funktionen nacheinander oder zeitgleich abgearbeitet werden, weiß ich nicht, nach welcher Art Fehler ich suchen muss.

Javascript meldet keine Fehler, aber macht es einfach nicht

// alle Audios auf halbe Lautstaerke
for ( let i=0; i<document.querySelectorAll( "audio" ).length; i++ ) document.querySelectorAll( "audio" )[i].volume = 0.2;

Habe den Dateien-Mix auf den Server geladen, damit ihr inspizieren könnt.

Vom Server geholt, wird jetzt (bei mir) die Tonart (C ist Standard) nicht gesetzt, das Ergebnis sieht so aus:

To|nika Do|minante Su|bdominante sollte so aussehen:

Gruß, Linuchs

  1. problematische Seite

    Moin Linuchs,

    window.addEventListener('DOMContentLoaded', function () {
    ...
    }
    

    funktioniert das denn überhaupt oder muss es eher

    document.addEventListener('DOMContentLoaded', function () {}
    

    sein?

    Viele Grüße
    Robert

    1. problematische Seite

      Hallo Robert,

      habe window. ersetzt durch document. beim DOMContentLoaded.

      Jetzt ist es umgekehrt, die Akkorde werden gesetzt, aber volume nicht verringert.

      Ist das ZUfall? Je nachdem, welche js-Datei zuerst fertig geladen ist?

      Gruß, Linuchs

      P.S. Ist window bei selfHTML auf dieser Seite richtig?

      1. problematische Seite

        Moin Linuchs,

        P.S. Ist window bei selfHTML auf dieser Seite richtig?

        Ja.

        Viele Grüße
        Robert

      2. problematische Seite

        Hallo Linuchs,

        ja, das Window-Objekt feuert ein load-Event und das Dokument ein DOMContentLoaded Event. Doof, aber wahr.

        Ist (die Reihenfolge) Zufall? Je nachdem, welche js-Datei zuerst fertig geladen ist?

        Jein. Falls Du deine Scripte asynchron laden würdest, dann ja.

        Ein script-Element, dass weder async noch defer noch type="module" hat, hält die DOM-Erzeugung an (ggf. sogar den HTML Parser, meine ich). Der Browser lädt das Script, führt es aus und DANN geht die DOM-Erzeugung weiter.

        D.h. 5 Scripte bewirken:

        • STOPP DAS DOM
        • Lade Script 1
        • WAAAAAARTE auf den Server
        • Führe Script 1 aus
        • WEITER MIT DOM - STOPP DAS DOM
        • Lade Script 2
        • WAAAAAARTE auf den Server
        • Führe Script 2 aus
        • ...
        • WEITER MIT DOM

        Heißt: Die DOMContentLoaded-Handler werden in der Reihenfolge der Script-Einbindungen registriert und auch in dieser Reihenfolge verarbeitet. Wenn Du das bezweifelst, bau in jeden Handler ein console.log("DOMContentLoaded von script ... wird ausgeführt"); ein.

        FALLS deine Scripte nichts weiter tun, als DOMContentLoaded-Handler zu registrieren - oder die Dinge, die sie außerdem tun, auch genauso gut im DOMContentLoaded-Handler stehen könnten. dann würde ich Dir empfehlen, auf DOMContentLoaded zu verzichten und den Script-Elementen statt dessen das Attribut defer zu geben. Das defer-Attribut wird hinreichend gut unterstützt. Mit defer angeforderte Scripte werden asynchron, also parallel zum DOM-Aufbau, geladen und nach Fertigstellung des DOM und nach Fertigladen der Stylesheets in der Reihenfolge der Anforderung ausgeführt. Wenn sie fertig sind, dann feuert DOMContentLoaded.

        Zu beachten ist dabei, dass DOMContentLoaded normalerweise nicht darauf wartet, dass die Stylesheets alle geladen sind. Aber DOMContentLoaded wartet auf defer-Scripte, und defer-Scripte warten darauf, dass die Stylesheets da sind. D.h. ein einziges defer-Script kann dazu führen, dass DOMContentLoaded auf das Fertigladen der Stylesheets wartet. Ob das ein Problem ist oder nicht, musst Du entscheiden.

        Noch besser wäre zweifellos, die Scripte mit type="module" zu laden (das impliziert defer), aber damit werden sie zu ECMAScript-Modulen mit allen Konsequenzen (sie laufen im strict mode und alles, was nicht exportiert wird, ist nur im Modul zugänglich). Ob das für deine Scripte taugt, musst Du für Dich entscheiden.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. problematische Seite

          Hallo Rolf,

          danke dir für den „Blick hinter die Kulissen“.

          Gruß, Linuchs

  2. problematische Seite

    Liebe Linuchs,

    in Deinem Code lese ich Unsinn.

    // alle Audios auf halbe Lautstaerke
    for ( let i=0; i<document.querySelectorAll( "audio" ).length; i++ ) document.querySelectorAll( "audio" )[i].volume = 0.2;
    

    Warum bildest Du zwei unterschiedliche Ergebnismengen, anstatt mit nur einer zu arbeiten? Unterschiedlich soll heißen, dass die Arrays nicht ein und das selbe Objekt sind, auch wenn ihre Inhalte (vielleicht!) identisch sind. Also schreibe das in Zukunft so:

    document.querySelectorAll("audio").forEach(function (audio) {
      audio.volume = 0.2;
    });
    

    Mit Pfeilfunktionen schreibt sich das noch besser:

    document.querySelectorAll("audio").forEach(audio => audio.volume = 0.2);
    

    Vom Server geholt, wird jetzt (bei mir) die Tonart (C ist Standard) nicht gesetzt, das Ergebnis sieht so aus:

    Keine Ahnung, was da genau nicht tut. Aber das verwendete DOM ist in meinen Augen nicht sinnvoll gewählt. Du willst Akkordsymbole anzeigen, die je nach Tonart dynamischen Inhalt bekommen. Dazu verwendest Du ein solches Markup:

    <div class=text style="font-size:180%;line-height:160%">
     <!-- (To)nika (Do)minante (Su)bdominante (Su7)-->
     <p class="akkorde"><l>1</l>
      Wa-(To)rum bist du gekommen, wenn (Do)du schon wieder gehst? <br>
      Du hast mein Herz genommen und (To)wirfst es wieder weg!<br>
      |: Ich (Su)bin kein Bajazzo, bin (To)auch ein Mensch wie du <br>
      und (Do)leise schlägt mein Herz dir (To)zu. :|</p>
    

    Der Validator ist jedenfalls überhaupt nicht zufrieden. Das solltest Du unbedingt in Ordnung bringen, bevor Du weiter nach Fehlfunktionen suchst!

    Meiner Ansicht nach sollte das Markup eher so sein:

    <ul class="lyrics">
      <li>
        <div>
          Wa-<span class="to"></span>rum bist du gekommen, wenn
          <span class="do"></span>du schon wieder gehst?
        </div>
        <div>
          Du hast mein Herz genommen und
          <span class="to"></span>wirfst es wieder weg!
        </div>
        ...
      </li>
    </ul>
    

    Die Klasse lyrics beschreibt, dass es sich um einen Liedtext handelt. Die Liste beschreibt die Strophen und ihre Reihenfolge. In CSS kann man also .lyrics li als Selektor für eine Strophe verwenden.

    Die jeweilige Liedzeile soll als Block-Element dargestellt werden, weil Du an ihrem Ende einen Zeilenumbruch notierst. Das kannst Du auch mit einem passenden Kindelement von li erreichen. Meine Wahl mit einem div ist vielleicht nicht die beste, aber es ist ein block-level element, das man hier verwenden könnte.

    Die eigentlichen Akkordsymbole werden in den leeren span-Elementen geregelt. Ihr Inhalt soll ja mit JavaScript beschrieben werden, deshalb habe ich sie inhaltsleer notiert. Über ihre Klasse kann man dann den Inhalt hineinschreiben. Der passende Selektor wäre .lyrics .to für Tonika-Akkorde - der Rest eben analog.

    Mit sinnvollerem Markup sollte auch das Hineinschreiben der Akkorde besser gelingen. Wenn es dann noch immer scheitert, obwohl das Markup vom Validator gesegnet wird und die JavaScript-Konsole keine Fehler wirft, dann kann man fragen, ob vielleicht DOMContentLoaded daran Schuld haben könnte, zu dem @Robert B. korrekt anmerkt, dass man das an das document-Objekt binden muss.

    Liebe Grüße

    Felix Riesterer

    1. problematische Seite

      @@Felix Riesterer

      Liebe Linuchs,

      Die Auswahl m/w/d überlässt du einer AI?

      // alle Audios auf halbe Lautstaerke
      for ( let i=0; i<document.querySelectorAll( "audio" ).length; i++ ) document.querySelectorAll( "audio" )[i].volume = 0.2;
      

      Warum bildest Du zwei unterschiedliche Ergebnismengen, anstatt mit nur einer zu arbeiten?

      Wenn man da schon mit for-Schleife rumhantieren will (Spoiler: will man nicht), dann so – mit einundderselben Ergebnismenge:

      const audios = document.querySelectorAll( "audio" );
      for ( let i=0; i<audios.length; i++ ) audios[i].volume = 0.2;
      

      Nach for eine Anweisung in derselben Zeile zu notieren ist auch eher bäh. Fehleranfällig. Sollte man nicht machen, sondern immer einen {}-Block verwenden.

      Mit Pfeilfunktionen schreibt sich das noch besser:

      document.querySelectorAll("audio").forEach(audio => audio.volume = 0.2);
      

      Statt forEach kann man[1] auch die for … of-Schleife verwenden:

      for (let audio of document.querySelectorAll("audio")) {
        audio.volume = 0.2;
      }
      

      Bei mir hieße die Variable nicht audio, sondern audioElement.

      Kwakoni Yiquan

      --
      Ad astra per aspera

      1. Auf Arbeit beim Tagesspiegel würden da die Alarmglocken des Linters schellen. Da ist for … of aus irgendeinem Grund verpönt, der sich mir jetzt nicht erschließt. ↩︎

      1. problematische Seite

        Die Auswahl m/w/d überlässt du einer AI?

        Ja klar, soll die doch verzweifeln, wie die Anrede wäre, wenn die audis gemischtgeschlechtlich sind.

    2. problematische Seite

      Hallo Felix,

      habe die Pfeilfunktion eingesetzt, keine Änderung des Verhaltens. Aber was dazugelernt heute.

      Deine Vorschläge

      Wa-<span class="to"></span>rum bist du gekommen, wenn
      <span class="do"></span>du schon wieder gehst?
      

      mögen technisch korrekt sein, aber macht den Quellcode unlesbar. Ich arbeite mit Texteditor.

      Statt 4 Zeichen (To) nun deren 24 <span class="to"></span>

      Gruß, Linuchs

    3. problematische Seite

      @@Felix Riesterer

      Meiner Ansicht nach sollte das Markup eher so sein:

      <ul class="lyrics">
        <li>
          <div>
            Wa-<span class="to"></span>rum bist du gekommen, wenn
            <span class="do"></span>du schon wieder gehst?
          </div>
          <div>
            Du hast mein Herz genommen und
            <span class="to"></span>wirfst es wieder weg!
          </div>
          ...
        </li>
      </ul>
      

      Meiner Ansicht nicht. Ein Liedtext ist keine Liste.

      Und wie würdest du mit Listen-Markup solch ein Lied hinbekommen wollen: 1. Strophe, 2. Strophe, Refrain, 3. Strophe, Refrain, 4. Strophe, Refrain?

      IMHO passt für Strophen und Refrains das p-Element mit br darin für die Zeilen – so wie ich es habe und wie Linuchs es auch hat.

      Noch besser wäre freilich ein natives HTML-Element für Zeilen. Das wurde bei der Entwicklung von HTML5 geflissentlich übersehen – dazu hätte Hixie ja eingestehen müssen, dass es auch Sinnvolles in XHTML2 gab (da war nähmlich ein l-Element geplant), und das wäre ihm wohl nie über die Lippen gekommen.

      Ich verwende deshalb ein custom element x-l, um die Einrückung hinzubekommen, wenn eine Liedzeile über mehrere Bildschirmzeilen geht.

      Und ja, custom elements haben einen - im Elementtypbezeichner, um sie von HTML-Elementen abzugrenzen. Das von Linuchs verwendete Phantasie-Element l verhält sich wie ein span[1] – sollte also keine Gefahr sein. Noch nicht. Das würde sich schlagartig ändern, wenn in HTML doch noch ein l-Element eingeführt wird.

      Dass Linuchs nicht l verwenden sollte, haben wir schon oft angesprochen. Er bleibt starrköpfig.

      Die eigentlichen Akkordsymbole werden in den leeren span-Elementen geregelt. […] Mit sinnvollerem Markup sollte auch das Hineinschreiben der Akkorde besser gelingen.

      Aber sowas von. Keine Ahnung, was Linuchs da treibt. Nach (To), (Do), (Su) suchen und durch Markup für die Akkorde ersetzen?

      Wenn man die Elemente schon im Markup hat (ruby/rt dürfte sich für Akkorde anbieten), muss nur noch deren Textinhalt ersetzt werden – das sollte einfacher und performanter sein.

      Wie sind denn eigentlich die Paralleltonarten benannt?

      Wenn ich sowas implementieren würde, würde ich Zahlen verwenden. Ist auch Standard: I für die Tonika, V für die Dominante, IV für die Subdominante. Paralleltonart der Tonika ist VIm; Paralleltonart der Dominante ist IIIm.

      Die Hälfte aller Lieder geht dann so: I – V – VIm – IIIm – IV – I – IV – V.

      Kwakoni Yiquan

      --
      Ad astra per aspera

      1. In der CSSBattle nutzt man das gnadenlos aus. Eine Lösung für Target 73 (Elephant) war <s><l><o><n><style>* *{margin:var(--m,-70-20);--p:0/50%;--:9q,#0000 42q,#998235}s{--:,#1A4341 0;--m:130}l{--m:31;--:at top,#0B2429 0 11q,#998235 0 21q,#0000 0;--p:0 62q/63q}o{--m:99-1-97;--p:0-60q;--:at bottom,#0000 5ch,#fff 0 63q,#0000}n{padding:68 20;--m:-10 40;--:,#0B2429 0}*{float:left;border-radius:1in;background:var(--p,3vw/47%)radial-gradient(4q var(--,9q,#0B2429 42q,#1A4341)42.7q.
        Fun fact: „slon“ heißt „Elefant“ in so ziemlich allen(?) slawischen Sprachen. ↩︎

  3. problematische Seite

    Hallo,

    // alle Audios auf halbe Lautstaerke
    for ( let i=0; i<document.querySelectorAll( "audio" ).length; i++ ) document.querySelectorAll( "audio" )[i].volume = 0.2;
    

    Du verwirrst dich, uns und alle anderen Leser deines Codes, wenn Kommentare nicht zum Code passen. Volume 0.2 ist nur dann halbe Lautstärke, wenn es vorher 0.4 war.
    Möchtest du durch 2 teilen oder auf 0.2 setzen?

    Gruß
    Kalk

    1. problematische Seite

      Hallo kalk,

      Volume 0.2 ist nur dann halbe Lautstärke, wenn es vorher 0.4 war.

      Die Einen sagen so, die Anderen so. Vor Jahren hatte ich die Information, dass die Lautstärke nicht linear, sondern logarithmisch geregelt wird.

      Aber auf Web-Informationen ist überhaupt kein Verlass. Wenn ich von 0.2 auf 1.0 gehe, nehme ich das als Verdoppelung wahr.

      Vielleicht kann mal jemand messen, ich habe kein solches Gerät.

      Gruß, Linuchs

  4. problematische Seite

    Moin Linuchs,

    Edit: Gunnar war schneller.

    Nachdem ich über das DOMContentLoaded-Event gestolpert bin, ist mir jetzt erst durch Tabellenkals Antwort noch etwas in diesem (langen und daher der Übersichtlichkeit halber umbrochenen) Einzeiler aufgefallen:

    // alle Audios auf halbe Lautstaerke
    for (let i = 0; i < document.querySelectorAll("audio").length; i++)
        document.querySelectorAll("audio")[i].volume = 0.2;
    

    Neben der Anmerkung von @Tabellenkalk, dass du die Lautstärke absolut auf 0.2 setzt – unabhängig von der vorher tatsächlich verwendeten Lautstärke, ist deine Schleife auch ziemlich ineffizient, weil die Selektoren n mal „gequeryd“ werden. Besser wäre einer der folgenden Ansätze:

    const audios = document.querySelectorAll("audio");
    
    // Explizite Schleife:
    for (let i = 0; i < audios.length; ++i) {
        audios[i].volume = 0.2;
    }
    
    // Einzeiler:
    audios.forEach((audio) => audio.volume = 0.2);
    

    Viele Grüße
    Robert

    1. problematische Seite

      Moin Robert,

      absolut auf 0.2 setzt – unabhängig von der vorher tatsächlich verwendeten Lautstärke

      Das läuft nach dem Laden des Dokuments und da sitzt das immer auf 1.0 - oder gibt es versteckte Schrauben, an denen man drehen könnte?

      Youtube Videos brüllen mir den ganz Wohnblock zusammen, wenn ich die bösen Cookies gelöscht habe. Ich verlasse den Firefox mehrmals am Tag, wer weiß, was der eingefangene Dreck alles anstellt.

      Cookies KRÜMELN überall hin. Sogar bis in die USA.

      Gruß, Linuchs

      1. problematische Seite

        Moin Linuchs,

        absolut auf 0.2 setzt – unabhängig von der vorher tatsächlich verwendeten Lautstärke

        Das läuft nach dem Laden des Dokuments und da sitzt das immer auf 1.0 - oder gibt es versteckte Schrauben, an denen man drehen könnte?

        also die Lautstärkeregelung meines Betriebssystems ist nicht jetzt nicht so versteckt …

        Youtube Videos brüllen mir den ganz Wohnblock zusammen, wenn ich die bösen Cookies gelöscht habe. Ich verlasse den Firefox mehrmals am Tag, wer weiß, was der eingefangene Dreck alles anstellt.

        Aber zumindest nicht die Lautstärkeeinstellungen des Betriebssystems verändern.

        Viele Grüße
        Robert

  5. problematische Seite

    Es gibt zwei Möglichkeiten um Skripte nach und nach zu ausführen zu lassen. Entweder du arbeitest im nächsten Script per EventListener ab ob das vorherige Script geladen wurde oder du machst das Ganze mithilfe von Promises.

    Dazu hier ein Beispielscript:

    function ladenDesSkripts(url) {
      return new Promise((resolve, reject) => {
        const skriptElement = document.createElement('script');
        skriptElement.src = url;
        skriptElement.onload = resolve;
        skriptElement.onerror = reject;
        document.head.appendChild(skriptElement);
      });
    }
    
    // Beispiel: Laden des ersten Skripts
    ladenDesSkripts('erstesSkript.js')
      .then(() => {
        console.log('Das erste Skript wurde geladen.');
        // Nachdem das erste Skript geladen wurde, lade das nächste Skript
        return ladenDesSkripts('zweitesSkript.js');
      })
      .then(() => {
        console.log('Das zweite Skript wurde geladen.');
        // Führe hier weitere Aktionen aus oder lade weitere Skripte
      })
      .catch((fehler) => {
        console.error('Ein Fehler ist aufgetreten:', fehler);
      });
    
    1. problematische Seite

      Hallo Hörnchen,

      Welches Problem haben nacheinander notierte Script Elemente, die du mit deinem Beispiel löst?

      Rolf

      --
      sumpsi - posui - obstruxi
      1. problematische Seite

        Sorry, ich hab den Text überflogen und diesmal nicht aufgepasst. Das passiert wenn man gerade programmiert auf einem Bildschirm und gleichzeitig Fragen beantworten möchte.