Linuchs: javascript: Array[0] nicht ansprechbar

Moin,

Nach dem Laden einer Webseite mit mehreren Audio- und Video-Tags muss ich wissen, welche das erste (Master) ist. Das sorgt für die Synchronisation des Textes (Karaoke).

<div class=em08>Instruments</div>
<audio controls preload="none">
  <source src="adiemus [music].mp3" type="audio/mpeg">
</audio>

<div class=em08>Voice</div>
<audio controls preload="none">
  <source src="adiemus [vocals].mp3" type="audio/mpeg">
</audio>

So funktioniert es nicht:

// Audios und Videos auf halbe Lautstaerke und addEvent canplaythrough
arr_ausgewaehlte_medien = document.querySelectorAll( "audio:not(.nogroup), video:not(.nogroup)" );
consoleOut( "lied_mehrspurig.js: " +arr_ausgewaehlte_medien.length +" Audios und Videos, Master ist [" +arr_ausgewaehlte_medien[0].src +"]" );

Meldung: lied_mehrspurig.js: 4 Audios und Videos, Master ist []

Bei einem einzelnen Video kann ich video.src setzen. Ist Setzen und Abfragen unterschiedlich?

Mir ist nicht klar, ob arr_ausgewaehlte_medien Pointer enthält oder Kopien. Die Kopie beeinflusst nicht das Original?

Lieben Gruß, Linuchs

  1. @@Linuchs

    <div class=em08>Instruments</div>
    <audio controls preload="none">
      <source src="adiemus [music].mp3" type="audio/mpeg">
    </audio>
    
    <div class=em08>Voice</div>
    <audio controls preload="none">
      <source src="adiemus [vocals].mp3" type="audio/mpeg">
    </audio>
    

    So funktioniert es nicht:

    // Audios und Videos auf halbe Lautstaerke und addEvent canplaythrough
    arr_ausgewaehlte_medien = document.querySelectorAll( "audio:not(.nogroup), video:not(.nogroup)" );
    consoleOut( "lied_mehrspurig.js: " +arr_ausgewaehlte_medien.length +" Audios und Videos, Master ist [" +arr_ausgewaehlte_medien[0].src +"]" );
    

    Meldung: lied_mehrspurig.js: 4 Audios und Videos, Master ist []

    Lass dir doch mal typeof arr_ausgewaehlte_medien[0] ausgeben. Dann schaust du nach, ob das ausgewählte Element ein src-Attribut hat. Wenn ja, dann wird dessen Inhalt auch ausgegeben. Wenn nicht, dann halt nicht. Guckst du.

    Kwakoni Yiquan

    --
    Ad astra per aspera
    1. Hallo Gunnar,

      danke, dein Tipp hat geholfen.

      Der src ist Typ string, aber leer.

      Der source src liest den Wert aus

      <audio controls preload="none">
        <source src="adiemus [music].mp3" type="audio/mpeg">
      </audio>
      
      <audio controls preload="none">
        <source src="adiemus [vocals].mp3" type="audio/mpeg">
      </audio>
      
      <audio controls preload="none">
        <source src="adiemus [bass].mp3" type="audio/mpeg">
      </audio>
      
      <audio controls preload="none">
        <source src="adiemus [drums].mp3" type="audio/mpeg">
      </audio>
      
      
      <script>
      var a = typeof document.querySelectorAll( "audio source" )[0].src;
      var b = document.querySelectorAll( "audio source")[0].src;
      console.log( "wert a=[" +a +"] wert b=[" +b +"]" );
      
      arr_ausgewaehlte_medien = document.querySelectorAll( "audio:not(.nogroup) source, video:not(.nogroup) source" );
      var a = typeof arr_ausgewaehlte_medien[0].src;
      var b = arr_ausgewaehlte_medien[0].src;
      console.log( "wert a=[" +a +"] wert b=[" +b +"]" );
      </script>
      

      Meldung:

      wert a=[string] wert b=[file:///home/kalle/musik/kalle/127%20adiemus/adiemus%20[music].mp3]

      wert a=[string] wert b=[file:///home/kalle/musik/kalle/127%20adiemus/adiemus%20[music].mp3]

      LG

  2. Lieber Linuchs,

    // Audios und Videos auf halbe Lautstaerke und addEvent canplaythrough
    arr_ausgewaehlte_medien = document.querySelectorAll( "audio:not(.nogroup), video:not(.nogroup)" );
    consoleOut( "lied_mehrspurig.js: " +arr_ausgewaehlte_medien.length +" Audios und Videos, Master ist [" +arr_ausgewaehlte_medien[0].src +"]" );
    

    Du holst Dir mit querySelectorAll so etwas ähnliches wie ein Array (genauer eine NodeList) mit Referenzen auf die DOM-Objekte. Deine Array-Schreibweise arr_ausgewaehlte_medien[0] ist syntaktisch richtig. Aber: Hat das erste Element auch eine Eigenschaft src, und wenn ja, ist ihr Wert in Stringform ein Leerstring?

    Du solltest unbedingt neben Deinem consoleOut noch dieses hier probieren:

    console.dir(arr_ausgewaehlte_medien[0]);
    

    Damit bekommst Du das Objekt auf der Konsole auf eine Art und Weise ausgegeben, bei der Du Dich durch seine Ebenen bewegen kannst, weil seine Darstellung ähnlich wie mit einem <details>-Element realisiert wird. Dort siehst Du dann auch, ob es eine Eigenschaft (oder Methode?) src gibt, und was sich dahinter verbirgt.

    Bei einem einzelnen Video kann ich video.src setzen. Ist Setzen und Abfragen unterschiedlich?

    Es stellt sich die Frage, was Du genau für ein Objekt bei arr_ausgewaehlte_medien[0] hast. Deine Debug-Ausgabe mit consoleOut ist in diesem Punkt zu spezifisch, weil sie eine Objekteigenschaft src ausgeben möchte, die das Objekt aber vielleicht nicht hat.

    Frage:
    Kannst Du Dir sicher sein, dass Dein Selektor so gewählt ist, dass das erste Element in der NodeList auch tatsächlich Deine führende Spur ist, oder ist es anhand Deines DOMs möglich, dass die Reihenfolge im Dokument manchmal eine andere ist, als Du sie in Deiner Liste erwartest?

    Frage:
    Kannst Du Deine Multimedia-Elemente erst sortieren, wobei Du das Merkmal der führenden Spur „nach oben sortierst“, damit Du sicher sagen kannst, dass [0] auf das Element mit der führenden Spur zeigt? Natürlich müsstest Du dafür sorgen, dass das Ergebnis von querySelectorAll zuerst in ein Array umgewandelt wird, weil das NodeList-Objekt keine Sortiermethode kennt.

    arr_ausgewaehlte_medien = Array.from(
      document.querySelectorAll( "audio:not(.nogroup), video:not(.nogroup)" )
    );
    
    arr_ausgewaehlte_medien.sort( (a, b) => {
      // <video> vor <audio> - oder implementiere ein anderes Merkmal
      if ("VIDEO" == a.tagName && "VIDEO" != b.tagName) {
        return -1; // a vor b, weil a ein <video> ist
      }
    
      if ("VIDEO" != a.tagName && "VIDEO" == b.tagName) {
        return 1; // b vor a, weil b ein <video> ist
      }
    
      // sekundäres Sortierkriterium hier
      //
    
      return 0; // Reihenfolge egal
    });
    

    Mir ist nicht klar, ob arr_ausgewaehlte_medien Pointer enthält oder Kopien. Die Kopie beeinflusst nicht das Original?

    Es werden keine Kopien angelegt. Das wäre ineffizient, weil die Objekte erst geklont werden müssten und das wiederum macht Vergleiche kaputt, weil a==b dann nicht mehr true ergeben kann.

    Liebe Grüße

    Felix Riesterer

    1. Lieber Felix,

      console.dir(arr_ausgewaehlte_medien[0]);
      

      Das ist ja stark, ein ganzer Roman. Ich sehe u.a.

      baseURI: "file:///home/kalle/musik/kalle/127%20adiemus/index.htm"
      currentSrc: "file:///home/kalle/musik/kalle/127%20adiemus/adiemus%20[music].mp3"
      

      Der currentSrc hat den gesuchten Wert, aber

      console.log(arr_ausgewaehlte_medien[0].currentSrc);
      

      ergibt <empty string>

      console.log(arr_ausgewaehlte_medien[0].innerHTML);
      

      ergibt

      <source src="adiemus [music].mp3" type="audio/mpeg">
      

      Da will ich mal zufrieden sein und kein Projekt draus machen. Vielen Dank.

      Lieben Gruß, Linuchs

      1. Hallo Linuchs,

        Der Inhalt von currentSrc ist dynamisch. Solange keine Wiedergabe läuft, ist es leer.

        Mit console.dir bekommst du das Objekt zum audio Element. Bis du soweit bist, das Objekt aufzuklappen, kann die Wiedergabe bereits begonnen haben. Gibst du currentSrc hingegen direkt beim Seitenstart aus, sind die Medien ggf. noch nicht geladen und das Attribut ist leer.

        Wie ist das mit deinem HTML? Hast du das source Element immer? Wenn ja, kannst du den Selektor im querySelectorAll so anpassen, dass du das source Element direkt bekommst. Mit Nachteilen, das zugehörige audio/video Element ist dann nur via parentElement erreichbar. Kommt halt darauf an, was du machen willst…

        Rolf

        --
        sumpsi - posui - obstruxi
        1. @@Rolf B

          Wie ist das mit deinem HTML? Hast du das source Element immer? Wenn ja, kannst du den Selektor im querySelectorAll so anpassen, dass du das source Element direkt bekommst. Mit Nachteilen, das zugehörige audio/video Element ist dann nur via parentElement erreichbar.

          Oder vielleicht besser andersrum? Man selektiert das audio/video-Element[1] und liest src von dessen source aus.

          Oder noch besser: man hält sich das offen. Man liest src vom audio/video-Element aus, wenn es existiert, ansonsten src von dessen source. Guckst du.

          Kwakoni Yiquan

          --
          Ad astra per aspera

          1. Mind the gap! ↩︎