View Single Post
Limited edition
Moff's Avatar
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å.