Grunnen til at du ikke skal bruke en timer, særlig ikke på så lite som ett sekund, er at dette feiler når musikken bruker mer enn ett sekund på å lastes ned. Det vil være svært problematisk for mobilbrukere over 4G, folk som sitter på dårlig tog- og/eller fly-wifi og slike ting. Det går sikkert bra for de av oss som har fiber - men du bør bruke en eventhandler, fordi den er designet for å kjøre koden når eventen skjer (altså når metadata er tilgjengelig).
Hvis du ser på koden jeg postet ovenfor, så bruker jeg getElementsByTagName for å hente alle <audio>-objekter i hele dokumentet. Jeg går gjennom hvert enkelt objekt med en for-loop. Det som skjer på innsiden av for-loopen er en såkalt IIFE (Immediately Invoked Function Expression). Fordi koden inne i eventhandleren er async (den kjører ikke i takt med resten av skriptet, den venter på signal), så kan jeg ikke referere til audio[i], fordi verdien av både audio og i-variabelen kan være endret når eventhandler-koden kjøres. En IIFE "låser" tilstanden til variablene, slik at jeg kan referere til dem på det tidspunktet IIFE-en ble kjørt. Dette fungerer fordi JavaScript har såkalt
function-scope, men det er et litt avansert tema som tar tid å forklare. Det som i praksis skjer er at jeg mater inn hver enkelt <audio> i variabelen "a" som sendes til eventhandleren. Den vil da vente til metadata er tilgjengelig for hvert enkelt <audio>-objekt, og deretter behandle a.duration, som er lengden på sangen i sekunder.
Linjen hvor jeg skriver console.log er der du kan legge inn logikk for hva du ønsker å gjøre med informasjonen. Hvis du vil oppdatere et heading-objekt, så kan du for eksempel legge inn en ID-referanse i audio-objektet som peker til riktig heading:
Kode
<h1>Bra låt (<span id="track-1"></span>)</h1>
<audio controls preload="metadata" data-header-id="track-1">
<source src="bra_låt.mp3" type="audio/mp3">
</audio>
<h1>Fet låt (<span id="track-2"></span>)</h1>
<audio controls preload="metadata" data-header-id="track-2">
<source src="fet_låt.mp3" type="audio/mp3">
</audio>
<h1>Chill låt (<span id="track-3"></span>)</h1>
<audio controls preload="metadata" data-header-id="track-3">
<source src="chill_låt.mp3" type="audio/mp3">
</audio>
<script>
var audio = document.getElementsByTagName("audio");
for(var i = 0; i < audio.length; i++) {
(function(a) {
a.onloadedmetadata = function() {
// Hent ID fra audio-objektet
var id = a.getAttribute("data-header-id");
// a.duration inneholder lengden i sekunder
var seconds = Math.floor(a.duration % 60);
var minutes = Math.floor((a.duration % 3600) / 60);
// Legg til leading zeroes, hvis du vil ("3:2" -> "03:02")
var duration = (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
// Skriv duration til heading-objektet
document.getElementById(id).innerHTML = duration;
};
})(audio[i]);
}
</script>
PHP-skriptet ditt må her sørge for å generere <h1>-objekter som inneholder en eller annen referanse (for eksempel en ID), og denne må samsvare med data-header-id-attributten på <audio>-objektene. Det er ingen fasit på hva som er beste løsning på denne problemstillingen. Du kan også få PHP-koden din til å lage en heading, et audio-objekt og en eventhandler for hver enkelt sang om du vil. Det er ikke like smooth, men det fungerer det også.