javascript: Array[0] nicht ansprechbar
Linuchs
- javascript
- medien
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
@@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
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
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
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
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
@@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
Mind the gap! ↩︎