Anzeige
Tutorialbeschreibung

mp3Player.js - ein HTML5-Audioplayer als JavaScript-Plug-In

mp3Player.js - ein HTML5-Audioplayer als JavaScript-Plug-In

In diesem Tutorial zeige ich euch, wie ihr einen auf HTML5, CSS und JavaScript basierenden Audioplayer als JavaScript-Plug-In erstellt, der ohne jQuery, Dojo, Mootools oder sonstige Frameworks funktioniert. Ihr könnt den Player via CSS hinterher vollkommen selbst gestalten und so tunen, dass er genau in eure Website passt.

Dabei lernt ihr nicht nur, ein Audioplayer-Plug-In in JavaScript zu schreiben, sondern auch etwas über einige generelle Aspekte von JavaScript, seine Tücken und Fallen sowie das Vermeiden von so genanntem "Spaghetti-Code".


Hallo und willkommen zu "mp3Player.js – ein HTML5-Audioplayer als JavaScript-Plug-In".

HTML5, Audio, Video ... das alles sind Schlagworte, die seit geraumer Zeit durch den virtuellen Raum schwirren, und beinahe jeder von uns hat sie schon einmal gehört. Leider ist die HTML5-Spezifikation des W3C zurzeit noch nicht wirklich ausgereift – fehlende Angaben der zu unterstützenden Codecs und daraus resultierende Browserdifferenzen, eine teilweise mangelnde oder unzureichende Browserunterstützung von neuen Tags usw.

Wer sich etwas tiefer mit der Materie beschäftigt, wird feststellen, dass zwar mittlerweile der Großteil der Browser die schönen neuen Media-Tags von HTML5 verarbeiten kann, die nativen Browserplayer aber vollkommen unterschiedlich aussehen, sodass auch hier wieder eine Differenz entsteht.

Abhilfe könnte hier die Steuerung der Inhalte über JavaScript bringen, aber ... wie?

Nun, genau das (und noch mehr) möchte ich euch hier zeigen. Wir werden zusammen ein Plug-In konstruieren, das folgende Features und Vorteile bietet:

• Eine ultraleichte Syntax – 1 Div, 1 Funktionsaufruf, ein bisschen CSS
• In der Gestaltung seid ihr vollkommen frei
• Play, Stop, lauter, leiser, Zeitanzeige bzw. Progressanzeige
• KEIN Framework benötigt – rein natives JavaScript
• User ohne HTML5-fähigen Browser bekommen einen Hinweis angezeigt
• Vermeiden des Zumüllens des globalen Namensraums (was das ist, erkläre ich später)

Noch eine Anmerkung:
Es geht hier um ein Lerntutorial – nicht darum, am Ende ein High-End-Plug-In zu besitzen, das alle möglichen Eventualitäten berücksichtigt. Es steht euch natürlich frei, entsprechende weitere Features in den Player zu integrieren.

Generell möchte ich anmerken, dass auch Anfänger dieses Tutorial durcharbeiten können und am Ende zu einem funktionierenden Ergebnis kommen werden. Dennoch richtet es sich eher an diejenigen unter euch, die schon etwas Erfahrung in JavaScript gesammelt haben. Damit möchte ich sagen, dass wir jedes Stück des Codes durchgehen werden, ich mir aber Erklärungen bis ins letzte Detail sparen werde. Interessante und wichtige Dinge klären wir natürlich ausführlich und wie immer stelle ich euch Verlinkungen mit genaueren Erklärungen und/oder wichtigen Ergänzungen bereit.

OK, dann mal los:


 

Schritt 1

Zunächst einmal wollen wir uns um den "Rahmen" unseres Plug-Ins kümmern. Damit schaffen wir quasi die Basics, die später an verschiedenen Stellen innerhalb des Plug-Ins genutzt werden.

Das Plug-In selbst wird in meinem Fall den gleichen Namen haben wie dieses Tutorial: "mp3Player".

Ihr erstellt also zunächst mal eine JavaScript-Datei im Editor eurer Wahl (ich nutze Dreamweaver CS5, andere gute Editoren sind Aptana Studio, Eclipse, Nodepad++ oder Weaverslave. Für JavaScript ist auch Netbeans hervorragend). Diese ist zunächst einmal wie folgt aufgebaut:
var mp3Player = (function(){
   var mp3Player, bind, connect, setAttr, createNode, fixEvt, is, toStr = Object.prototype.toString;
}());


1.

Die erste Variable bestimmt hinterher, wie das Plug-In aufgerufen wird. In diesem Fall via mp3Player(). Würdet ihr dort beispielsweise "myAudioPlayer" schreiben, würde das Plug-In hinterher via myAudioPlayer() initialisiert werden.

In diesem Beispiel wird "mp3Player" eine (und zwar die einzige) Variable sein, die im globalen Namensraum verfügbar sein wird. Als globalen Namensraum bezeichnet man in JavaScript alles, was direkt innerhalb des obersten Objektes in der Objekthierarchie verfügbar ist. Als oberstes Objekt der Objekthierarchie innerhalb eines Browsers bezeichnet man das window-Object. mp3Player wird also ein direkter Nachkomme des window-Objects werden.

In der Einleitung habe ich ja schon davon gesprochen, dass unser Plug-In den globalen Namensraum (auch "global Scope" genannt) so wenig wie möglich erweitern wird. Der Grund für diese Vorgehensweise ist relativ einfach: Die Gefahr des unabsichtlichen Überschreibens von Objekten innerhalb des global Scope soll so weit wie möglich minimiert werden, um Namensraumkollisionen zu vermeiden. Es gibt eine grundsätzliche Regel für das Erstellen von Modulen bzw. Plug-Ins in JavaScript, die wie folgt lautet:

"Ein Modul sollte dem globalen Namensraum nie mehr als ein einziges Symbol hinzufügen."

Wer mehr darüber erfahren möchte, wieso das so wichtig ist, kann hier nachlesen.


2.

Danach definiere ich eine sich selbst aufrufende Funktion, deren Rückgabewert ich in mp3Player speichere. Was das bedeutet, erklärt man am besten anhand eines Beispieles:

Wenn ihr normalerweise eine Function deklariert, sieht das so aus:
// Function deklarieren, Variante 1:
function meineFunktion(){
      // mach irgendetwas Cooles
}

// Variante 2:
var meineFunktion = function(){
      // mach irgendetwas Cooles
}

// Variante 3, am seltensten genutzt
var meineFunktion = function meineFunktion(){
      // mach irgendetwas Cooles
}


Soll "meineFunktion" dann ausgeführt werden, geschieht der Aufruf auf folgende Weise:
meineFunktion();

Prinzipiell passiert im grün markierten Teil auch nichts anderes. Es wird eine Function deklariert, die direkt nach der Deklaration aufgerufen wird. Leider ist es in JavaScript allerdings nicht einfach möglich, var meineFunktion = function(){}() zu schreiben. Dies kommt daher, dass der JavaScript-Interpreter dieses Konstrukt nicht verarbeiten kann. Ändert man die Schreibweise aber in var meineFunktion = (function(){}()), kann der Interpreter die Anweisung verarbeiten, weil der Teil innerhalb der äußersten Klammern zu einem Ausdruck wird.


3.

Die restlichen Teile des Codes, also die inneren Variablen (sog. "Closures") mp3Player, bind, connect, setAttr, createNode etc., nutzen wir später innerhalb des Codes unseres Plug-Ins. Wir machen daraus sogenannte "Helper functions". Und das bringt uns auch schon zu Schritt 2.


 

Schritt 2

Nach diesem eher theoretischen Part werden wir erst mal unser Rahmengerüst ausbauen und die Hilfsfunktionen erstellen. Das geht so:
var mp3Player = (function(){

var mp3Player, bind, connect, setAttr, createNode, fixEvt, is, toStr = Object.prototype.toString;

/* HELPERS
-----------------------------------------------------------------------------------------------*/
/* Liefert eine function zurück, innerhalb derer die ursprünglich
 * übergebene function mit (halbwegs) normalisiertem event-
 * object auf elem aufgerufen wird
*/
bind = function(func, elem){
   return function(event){
      var e = fixEvt(event, elem);
      func.call(elem, e);
   };
};

/* Liefert ein (halbwegs) normalisiertes event-object zurück,
 * das in MSIE < V9 gleich funktioniert wie in FF, O, GC, SF...
*/
fixEvt = function(event, node){
   var e = event || window.event;
   if(!e.target){ e.target = e.srcElement || node; };
   if(!e.preventDefault){ e.preventDefault = function(){ e.returnValue = false; }};
   if(!e.stopPropagation){ e.stopPropagation = function(){ e.cancelBubble = true; }};
   e.stopEvent = function(){ e.preventDefault(); e.stopPropagation(); };
   return e;
};

/* Bindet einen EventListener an einen DOM-Knoten, dessen Handler
 * bei via type spezifiziertem Event ausgeführt wird.
*/
connect = function(elem, type, func){
   if(elem.addEventListener){
      elem.addEventListener(type, bind(func, elem), true);
   } else if(elem.attachEvent){
      elem.attachEvent('on' + type, bind(func, elem));
   } else {
      elem['on' + type] = bind(func, elem);
   }
};

/* Setzt Attribute in DOM-Knoten. attrs muss vom Typ Object sein! */
setAttr = function(elem, attrs){
   var x;
   for(x in attrs){
      if(attrs[x] !== null && typeof attrs[x] !== 'undefined'){
         elem.setAttribute(x, attrs[x]);
      }
   }
};

/* Erzeugt einen neuen DOM-Knoten und gibt diesen zurück. Sofern
 * attrs angegeben, werden die definierten Attribute gesetzt.
*/
createNode = function(tagname, attrs){
   var node = document.createElement(tagname);
   if(attrs && is(attrs, 'object')){
      setAttr(node, attrs);
   }
   return node;
};

/* Prüft den Typ von thing anhand von shouldBe, gibt bei Über-
 * einstimmung true zurück, ansonsten false. Genauer als der
 * typeof-Operator in JavaScript. Beispiele:
 *
 * is([], 'array') ==> true
 * is([], 'object') ==> false
 * is('array', 'array') ==> false
 * is(new Array(), 'array') ==> true
 *
*/
is = function(thing, shouldBe){
   return (toStr.call(thing).replace(/^\[object\s+|\]$/g, '').toLowerCase()) === shouldBe;
};

/* PLUGIN-CORE
----------------------------------------------------------------------------------------- */
mp3Player = function(idSelector, optionsObject){
return new mp3Player.prototype.initialize(idSelector, optionsObject);
};

mp3Player.prototype = {};

mp3Player.prototype.initialize.prototype = mp3Player.prototype;

return mp3Player;
}());

Keine Panik, es sieht viel schlimmer aus, als es in Wahrheit ist! Der größte Teil dieses Codes besteht aus Kommentaren, die kurz erläutern, was die entsprechenden Hilfsfunktionen tun. In eurem Code könnt ihr, wenn ihr wollt, die Kommentare natürlich auch auslassen.

 
Logisch zusammengehörige Teile habe ich als Sektionen zusammengefasst:

• Helpers – Hilfsfunktion, die uns die Arbeit erleichtern
• Plugin-Core – Kernteile des Plug-Ins, daran arbeiten wir jetzt weiter

Wirklich wichtig sind also die unter PLUGIN-CORE fallenden Teile. Die folgenden Erklärungen beziehen sich also auf den unteren Teil des Codes.

Mit mp3Player = function(idSelector, optionsObject) deklarieren wir eine innere Funktion, die dazu dient, einen neuen Player zurückzugeben. Dies geschieht über die im prototype-Object enthaltene Function (in solchen Fällen sagt man dazu "Methode") initialize().

Wer sich an dieser Stelle fragt, was denn ein prototype-Object ist, bekommt hier die Erklärung:

Ein prototype-Object dient quasi als "Bauplan" für neu erzeugte Objekte. Jedes neu erzeugte Objekt enthält automatisch alle Eigenschaften und Methoden seines prototype-Objects (sogenannte "Vererbung"). Wer genau hinsieht, wird bemerken, dass innerhalb der Function "mp3Player" folgende Anweisung steht:
return new mp3Player.prototype.initialize

Das Schlüsselwort new sagt dem JavaScript-Interpreter, dass ein neues mp3Player-Objekt erzeugt werden soll. Tiefer in diese Materie kommen wir aber gleich.

Mit der Anweisung return wird dem Interpreter gesagt, dass das neue mp3Player-Objekt zurückgegeben werden soll.

In der darauf folgenden Zeile erzeuge ich das prototype-Object mit
mp3Player.prototype = {};

Kommen wir jetzt zum wahrscheinlich wichtigsten (und von der Logik schwierigsten) Punkt:
mp3Player.prototype.initialize.prototype = mp3Player.prototype;

Wem jetzt auf Anhieb klar ist, was hier passiert, der hat verstanden, was das prototype-Object ist. Alle anderen müssen sich wohl oder übel durch meine folgende Erklärung quälen: ;)

 
Mit dieser Zeile wird definiert, dass das prototype-Object von mit initialize() neu erzeugten Objekten das gleiche sein soll wie von mp3Player. Das bedeutet, jedes neu erzeugte mp3Player-Objekt hat ein prototype-Object, das beispielsweise eine initialize-Methode enthält. Es hat diese Methode, weil das prototype-Object von mp3Player die Methode enthält. Im weiteren Verlauf werden wir das prototype-Object von mp3Player um Methoden und Eigenschaften erweitern, und so stellen wir sicher, dass diese später in jedem Player zur Verfügung stehen.

Alle, die es trotz meiner Erklärung nicht verstanden haben: Keine grauen Haare bekommen! Es handelt sich hier um eines der wahrscheinlich komplexesten (Logik-)Themen, die JavaScript zu bieten hat, bis man es einmal verstanden hat. Danach ist es kinderleicht :) . Weitere Erklärungen dazu finden sich hier und hier.


Schritt 3

Ab diesem Punkt arbeiten wir nur noch innerhalb des prototype-Objects von mp3Player. Bedenkt dabei bitte, dass wir hier in der Object-Notation arbeiten.
mp3Player.prototype = {
   constructor : mp3Player,
   initialize : function(idSelector, optionsObject){

   },
   onInit : function(self){

   },
   setReady : function(self){

   }
};

Das ist jetzt mal erfreulich kurz (zumindest bis jetzt).

Mit constructor wird angegeben, welche Funktion das prototype-Object (da ist es wieder) enthält. Das ist, eine Zeile darüber unschwer zu erkennen, mp3Player.

Dann deklarieren wir 3 weitere Methoden des prototype-Objects:

• initialize, mit 2 Parametern
• onInit, 1 Parameter
• setReady, 1 Parameter

Sobald diese 3 fertig sind, ist das Plug-In einsatzbereit! Dann mal fröhlich weiter im Text ...


 

Schritt 4

Zunächst befassen wir uns mit der initialize-Methode. Hier speichern wir alle nötigen und optionalen Angaben in unsere neuen Player-Objekte:
mp3Player.prototype = {
   constructor : mp3Player,
   initialize : function(idSelector, optionsObject){
      var optionsObject = optionsObject || {};

      /* Bei fehlender benötigter Angabe oder falschem Parameter den Initialisierungsprozess abbrechen und eine Fehlermeldung ausgeben. */
      if(!is(idSelector, 'string') || !is(optionsObject, 'object') || !optionsObject.tracks){
         throw new Error('One or more parameters are wrong! Could not initialize mp3Player()!');
      }

      /* Elemente holen, Einstellungen speichern */
      /* Zuerst "must have's" */
      this.root = document.getElementById(idSelector);
      this.tracks = optionsObject.tracks;

      /* Optionale Einstellungen */
      this.preload = optionsObject.preload || 'metadata';
      this.initVolume = optionsObject.initVolume || 0.8;
      this.volumeStep = optionsObject.volumeStep || 0.2;
      this.onEvent = optionsObject.onEvent || 'click';

      /* Ist this.tracks kein Array? Dann mach eines daraus */
      if(!is(this.tracks, 'array')){
         this.tracks = [ this.tracks ];
      }

      /* Player initialisieren, wenn der Browser das <audio>-Tag unterstützt */
      if(this.onInit(this)){
         this.setReady(this);
      }

      return this;
   },
   onInit : function(self){

   },
   setReady : function(self){

   }
};

 
Generell wichtig ist hier nur, dass "this" auf das prototype-Object des neuen Players verweist. Die Arbeit mit "this" in JavaScript bietet leider einige Tücken und viel Fehlerpotenzial. Generell gilt:

"this verweist immer auf das aufrufende Object".

Eine Anekdote zum Schmunzeln: Douglas Crockford hat einmal den Satz "this is wrong" geprägt, nachdem er seinen Fehler in einem Stück JavaScript-Code gefunden hatte.

Der Ablauf des Codes innerhalb von initialize ist grob beschrieben folgender:

• Klone den "optionsObject"-Parameter oder, falls er nicht gegeben ist, mach daraus ein leeres Object.
• Prüfe, ob alle erforderlichen Parameter übermittelt wurden und ob diese vom richtigen Typ sind. Falls nicht, wirf einen Fehler aus und brich die Initialisierung ab.
• Suche dem DOM-Knoten mit dem "idSelector"-Parameter und speichere ihn intern ab.
• Speichere die übergebenen Pfade zu den Tracks, die im optionsObject stehen.
• Speichere die weiteren Einstellungen. Wurden diese nicht getroffen, setze Default-Werte ein.
• Rufe onInit() mit einer Referenz auf das Player-Objekt auf. Wenn onInit() erfolgreich war, rufe setReady() auf.
• Gib das Player-Objekt zurück.


Schritt 5

Befassen wir uns nun mit der onInit-Methode. Hier nutzen wir massiv unsere zu Anfang definierten Hilfsfunktionen, um neue DOM-Knoten zu erzeugen und mit Attributen zu versehen. Zusätzlich zeige ich euch, wie ihr sogenannte Memory-Leaks vermeidet. Als Memory-Leak bezeichnet man die Situation, wenn der Speicher des Browsers mit Daten gefüllt wird, die nicht automatisch zur Garbage Collection (sozusagen JavaScripts-Müllhalde) kommen.
mp3Player.prototype = {
   constructor : mp3Player,
   initialize : function(idSelector, optionsObject){
      /* Das hatten wir gerade... */
   },
   onInit : function(self){
      var self = self, audio, src, playBtn, stopBtn, progDiv, progress, 
                    volUp, volDown, hint, x, knowsTag = false;

      /* Elemente erzeugen */
      audio = createNode('audio', { preload : self.preload });
      playBtn = createNode('div', { 'class' : 'mp3Player_playButton' });
      stopBtn = createNode('div', { 'class' : 'mp3Player_stopButton' });
      progDiv = createNode('div', { 'class' : 'mp3Player_progressContainer' });
      progress = createNode('div', { 'class' : 'mp3Player_progressBar' });
      volUp = createNode('div', { 'class' : 'mp3Player_volumeUp_Button' });
      volDown = createNode('div', { 'class' : 'mp3Player_volumeDown_Button' });
      hint = createNode('p');

      /* Kennt der Browser das <audio>-Tag und kann damit arbeiten? */
      if(is(audio.play, 'function')){
         knowsTag = true;
      }

      hint.innerHTML = 'Dieser Browser unterstützt das Audio-Tag leider nicht.';

      /* Das Folgende nur ausführen, wenn der Browser das <audio>-Tag unterstützt */
      if(knowsTag){
         audio.volume = self.initVolume;
         progress.style.width = '0%';

         /* Elemente in das DOM einfügen */
         self.root.appendChild(playBtn);
         self.root.appendChild(stopBtn);
         self.root.appendChild(volUp);
         self.root.appendChild(volDown);
         progDiv.appendChild(progress); 
         self.root.appendChild(progDiv);

         for(x = 0; x < self.tracks.length; x = x+1){
            src = createNode('source', { src : self.tracks[x] });
            audio.appendChild(src);
         }

         audio.appendChild(hint);
         self.root.appendChild(audio);

         /* Elemente speichern */
         self.audio = audio;
         self.play = playBtn;
         self.stop = stopBtn;
         self.progress = progress;
         self.volBtns = [ volUp, volDown ];
      } else {
         /* Wenn der Browser das <audio>-Tag nicht kennt, zeige nur den Hinweis */
         self.root.appendChild(hint);
      }

      /* Memory Leaks verhindern */
      audio = null;
      playBtn = null;
      stopBtn = null;
      progress = null;
      progDiv = null;
      volUp = null;
      volDown = null;
      hint = null;
      src = null;

      /* Erfolg? */
      return knowsTag;
   },
   setReady : function(self){

   }
};

Die Kommentare innerhalb des Codes sollten eigentlich klarmachen, was passiert.

Zunächst werden mit der Hilfsfunktion "createNode" die erforderlichen HTML-Elemente erzeugt und mit Attributen versehen. Im Anschluss wird überprüft, ob der Browser das Audio-Tag kennt und es eine Methode namens "play" hat. Ist dies der Fall, wird die Variable "knowsTag" auf true gesetzt.

Sofern "knowsTag" true ist, werden via appendChild() die erzeugten HTML-Elemente in das in initialize() gespeicherte Root-Element eingefügt. Falls nicht, wird nur ein <p>-Tag eingefügt mit dem Hinweis, dass dieser Browser das HTML5-Audiotag leider nicht unterstützt. An dieser Stelle könntet ihr, sofern ihr wollt, anstatt eines Hinweises auch ein Flashfallback einbauen für alle Browser, die das Audiotag nicht unterstützen.

Nachdem die erzeugten HTML-Element-Referenzen innerhalb des Players gespeichert wurden, werden die innerhalb der Variablen gespeicherten Referenzen auf null gesetzt. Damit weiß der Garbage Collector, dass diese Referenzen im weiteren Verlauf des Scripts nicht mehr benötigt werden und dadurch Ressourcen wieder freigemacht werden können.

Am Ende der Methode wird, sofern das HTML-Audiotag unterstützt wird, true, ansonsten false zurückgegeben.


 

Schritt 6 – Endspurt

Fast geschafft. Jetzt fehlt nur noch die setReady-Methode. Diese sieht wie folgt aus:
mp3Player.prototype = {
   constructor : mp3Player,
   initialize : function(idSelector, optionsObject){
      /* Das hatten wir vorhin... */
   },
   onInit : function(self){
      /* ... und das hatten wir gerade */
   },
   setReady : function(self){
      var self = self;

      /* EventListener auf DOM-Knoten registrieren */
      connect(self.play, self.onEvent, function(){ 
         self.audio.play(); 
      });

      connect(self.stop, self.onEvent, function(){ 
         self.audio.pause(); 
         self.audio.currentTime = 0; 
      });

      connect(self.volBtns[0], self.onEvent, function(){ 
         if((self.audio.volume + self.volumeStep) < 1){ 
            self.audio.volume += self.volumeStep; 
         }
      });

      connect(self.volBtns[1], self.onEvent, function(){ 
         if((self.audio.volume - self.volumeStep) > 0){ 
            self.audio.volume -= self.volumeStep; 
         }
      });

      /* Aufgepasst, hier verweist "this" auf das Audio-Element! */
      connect(self.audio, 'timeupdate', function(){
         var t = this.duration, c = this.currentTime;
         self.progress.style.width = ((c / t) * 100) + '%';
      });
   }
};

Genau genommen passiert in setReady() nichts Aufregendes mehr. Wir registrieren nur einige Eventlistener auf unseren Player-Buttons und sagen mit dem letzten connect(), dass bei einem Weiterspringen des Videokopfes auf der Zeitleiste die Weite der sichtbaren Progressbar prozentual angepasst werden soll.

Interessant ist, dass sowohl play() und pause() als auch "duration" und "currentTime" native Methoden und Eigenschaften des Audio-Tags sind. Letztere sind allerdings beide nur dann verfügbar, wenn bei der Initialisierung des Players in optionsObject.preload = 'metadata' oder preload = 'auto' gesetzt ist. Bei keiner Angabe wird automatisch 'metadata' genutzt.

Der Grund hierfür ist einfach: 'auto' bewirkt, dass beim Laden der Website sofort auch das Laden des Videos beginnt. Wer einmal mit einem Handy und langsamer Verbindung im Internet unterwegs war, der kann sich vorstellen, wie nervig es ist, wenn eine komplette mp3- oder ogg-datei direkt bei einem Seitenaufruf mitgeladen wird.


Finish

Das war's. Jetzt sind wir soweit, dass wir unser Plug-In nutzen können. Dafür müsst ihr nur Folgendes tun:

1.)
Die JavaScript-Datei einbinden. Dies geschieht über ein <script>-Tag im head der Seite.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>mp3Player.js - Ein HTML5 Audioplayer als Javascript Plug-In</title>
<script src="mp3player.js"></script>
</head>
<body>
...


2.)
Ein Div in der Seite notieren. Gebt ihm beispielsweise die id "div_mp3player".
<body>
<div id="div_mp3player"></div>
</body>


3.)
Irgendwo innerhalb der Page ein zweites <script>-Tag notieren. Dort schreibt ihr Folgendes:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>mp3Player.js - Ein HTML5-Audioplayer als JavaScript-Plug-In</title>
<script src="mp3player.js"></script>
<script>
//<![CDATA[
window.onload = function(){
    mp3Player('div_mp3player', { tracks : [ 'pfad/zur/mp3', 'pfad/zur/ogg'] });
};
//]]>
</head>
<body>
<div id="div_mp3player"></div>
</body>

In den bereitgestellten Arbeitsdateien findet ihr einmal die Bilder, die für meine Gestaltung des Players, wie sie im Bild des Tutorials dargestellt ist, nötig sind, sowie eine kleine CSS-Datei mit den entsprechenden Stylesheet-Definitionen.

Fertig! Ich hoffe, dass ihr während dieses Tutorials Spaß hattet und euch ein wenig mehr über das Schreiben von JavaScript-Plug-Ins bzw. über JavaScript im Allgemeinen verständlich wurde.

Ich wünsche euch ansonsten noch viel Freude an diesem Plug-In!

DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von wmquint
  • 19.03.2014 - 23:41

Hi,
irgentwas mache ich falsch. Ich bin kein richtiger Programmierer, die einzige Sprache, die ich kenne ist ActionScript 2 - ich habe früher mit Flash 8 programmiert, u.a. MP3 Player. Jetzt brauche ich ein Player, der auf Apple Tablet funktioniert, und Flash kommt nun nicht mehr in Frage.
Ich habe auch den code kopiert und mit GoLive 9 daraus eine mp3player.js und eine .html erstellt, aber bei mir ist nichts zu sehen.
Komme mit dem Script nicht klar. Wollte in workfile die Hilfe finden, aber da sind auch keine .js oder .html File, nur Bilder, Musik und 2 .css.

Portrait von besercer
  • 25.06.2012 - 16:29

Also irgendwie wird bei mir nichts angezeigt :/ hab den Code so kopiert wie er da steht und trozdem wird mir nur eine leere Seite angezeigt :( was mache ich falsch?

Portrait von mindraper
  • 25.06.2012 - 21:46

hi @besercer,

hast du irgendwo einen link zu deinem code? dann könnte man mal drauf schauen.

generell: den code einfach so wie er da steht zu kopieren bringt nichts, weil ich ihn pro sektion nochmal gegliedert hatte. wenn du einfach nur kopierst, hat das folgende wirkungen:

a) du verstehst nicht wirklich was ich da gemacht habe.
b) teile des späteren codes überschreiben vorhergehende.

lade dir doch mal das workfile runter und schau es dir an. da ist der komplette code drin enthalten, sofern du gar nicht weiterkommst.

als quasi unerlässliches tool hat sich auch immer wieder firebug bewährt, wenn es darum geht, fehler in codestücken zu finden. falls du auf google chrome, safari oder opera arbeitest, kannst du natürlich auch die darin enthaltenen tools nutzen (rechtsklick auf die page - element untersuchen - auf den reiter "console" wechseln). codefehler werden dort mit zeilenangabe ausgeworfen.

leider ist es mir nicht möglich, dir momentan mehr zu sagen. ich kann deinen code ja nicht sehen :). falls es gar nicht funzt - pm an mich. ich bin (fast) jeden tag hier online. oder du schreibst mir eine mail. adresse steht in meinem profil.

cheers!

Portrait von besercer
  • 27.06.2012 - 13:24

vielen Dank! Ich habs mir noch mal auf der Arbeit erklären lassen und nun klappts. Danke :)

Portrait von Hanno_Hauser
  • 24.06.2012 - 12:17

Hi,
danke für die gute Erklärung.
LG

Portrait von mindraper
  • 23.06.2012 - 19:34

@all:

danke für euer freundliches feedback! :)

dann macht es auch spaß solche tuts zu schreiben!

Portrait von DaKKK
  • 23.06.2012 - 15:08

Vielen Dank :-) Super erklärt!

Portrait von MicroSmurf
  • 23.06.2012 - 13:14

Sehr hilfreich. Danke.

Portrait von MaoMao
  • 23.06.2012 - 13:09

Danke für das tolle Tutorial imkl der Workfile.

Portrait von johanna52
  • 23.06.2012 - 12:57

danke für das sehr gut erklärende Tut.

x
×
×