Tutorial

20

Click here to load reader

Transcript of Tutorial

Page 1: Tutorial

In this tutorial I will show you how to create a JavaScript MP3 Player with jQuery and the SoundManager 2JavaScript library that uses a hidden SWF file to play the sounds.

Step 1: Getting the Libraries

In this step we will download all the files we will need throughout this tutorial. We will be using thefollowing libraries:

jQuery: A general purpose JavaScript libraryjQuery UI: A user interface library built on top of jQueryjScroller: A jQuery plugin that provides scrolling capabilities to textSoundManager 2: A library that wraps Flash’s Audio API in JavaScript

Now we will download these and save them to a convienient directory for future use.

Head over to the jQuery.com site and download the production version of jQuery.

We need to download a version of the jQuery UI library. This library comes with many different themes; theone we will be using is called “smoothness”. Point your browser to jQueryUI.com, and on the right side ofthe page choose “smoothness” from the pulldown menu then click the Download button. You can pick andchoose what you want to include in the download, but for the purposes of this tutorial we will just leaveeverything checked. (If you decide to put this live on a server you’ll probably want to choose just what isnecessary, to save a little bit of bandwidth.)

Go to code.google.com and download the jScroller plugin.

Lastly, to get the SoundManager2 library head over to schillmania.com.

Page 2: Tutorial

Step 2: Project Structure

Instead of explaining step by step how to set up the project folder structure, I have provided a “start.zip” inthe download files.

Basically, I moved all the JavaScript files into the “js” folder and the CSS files into the “css” folder. Also,inside the css and js folders I have included the files “mp3player.css” and “mp3player.js”, respectively. The“mp3player.css” already has the CSS written for positioning the MP3 player images. I will not be going intomuch depth on the CSS, as the focus of this tutorial is on the JavaScript. The “mp3player.js’ is blank rightnow.

The “start.zip” also contains the following files/folders:

“images”: holds the images for the mp3player“swf”: holds the .SWF files used by SoundManager“sounds”: holds the MP3s“index.html”: the main HTML page

You will need to extract this file on a server, as SoundManager 2 will not work otherwise, and will throw anerror. I am using local setup with WAMP.

The downloadable ZIP also contains a copy of the source from every Step of this tutorial, to make it easy tofollow along.

Step 3: Examining index.html

Open index.html in a text editor and have a look at its structure. The index.html includes the JavaScript/CSSfiles, and the image and div tags for the MP3 Player. It is important that you follow the structure of thisHTML file when including the .js files, as we need the jQuery.js files to load before the soundmanager.jsfile. (Throughout this tutorial I will refer to the images as “buttons”, because that is what they are actinglike.)

Below is an image showing the IDs of the images and divs that make up the MP3 Player:

Page 3: Tutorial

Step 4: Document ready()

Open “mp3player.js”, located in the “js” folder and enter the following code.

1234

private function demonstrate():void$(document).ready(function() { alert("Document Ready");});

If you now open index.html, you’ll see an alert with the words “Document Ready”. jQuery’s .ready()method gets called when the DOM has fully loaded and is available for manipulation.

It is important to call this method when writing your applications, because if you try to start manipulatingDOM elements before they are loaded it will have no effect. For instance, if you tried to add a click handlerto a button before it has loaded it would have no effect.

Here is a link to the .ready() method in the jQuery documentation.

Step 5: SoundManager onready()

Add the following code within the $(document).ready you added in the step above.

12345678

$(document).ready(function() { alert("Document Ready"); soundManager.url = 'swf'; soundManager.flashVersion = 8; soundManager.onready(function() { alert("SoundManager Ready"); });});

Here we set up the soundManger.url which points to the directory we have the SWF files in, set thesoundManager.flashVersion to 8, and call soundManager.onready().

The onready() method of SoundManager works very much the same way as jQuery’s .ready() method.When soundManager has fully loaded it fires off the .onready() method, and signals that we can startadding properties to and calling methods on the SoundManager object. When we load “soundManager.js” itautomatically creates a global SoundManager object, aptly named soundManager, so there no need to say:

1var soundManager = new SoundManager();

The documentation for SoundManager is available on schillmania.com.

Step 6: playSound()

Enter the following code within mp3player.js:

0102030405060708091011

$(document).ready(function() { soundManager.url = 'swf'; soundManager.flashVersion = 8; var theMP3; var currentSong =0; soundManager.onready(function() { function playSound(){ theMP3= soundManager.createSound({ id:'sound'+currentSong, url:"../sounds/1.mp3" });

Page 4: Tutorial

1213141516

theMP3.play(); }; playSound(); });});

Here we set up two global variables: theMP3 and currentSong. The theMP3 variable is used with thecreateSound() method of SoundManager, and the currentSong variable will be used to keep track of whichtrack is playing (it will always be a number).

Within the .onready() method, we create a function playSound(), and inside this function we call thecreateSound() method of SoundManager using our theMP3 variable. We set a id and a url to the MP3 file,and tell the MP3 to play by calling theMP3.play(). Lastly we call the playSound() function which plays theMP3.

If you open index.html now you should hear the MP3 playing. At this point there are 5 MP3 files in the“sound” folder. (I have stored this folder a level above the index.html, so the zip file would not containmultiple copies of the MP3s, and each step in the tutorial can use the same folder. You don’t have to dothis, of course.)

The MP3s used in this tutorial are all public domain, and are fromhttp://funfunfunmedia.com/author/publicdomain2ten.

Step 7: Play Button

Being able to play the MP3s is all well and good, but we want some control over the MP3. In this step wewill “wire up” the play button. Add the following code to “mp3player.js”:

010203040506070809101112131415161718

soundManager.onready(function() { function playSound(){ theMP3= soundManager.createSound({ id:'sound'+currentSong, url:"../sounds/1.mp3" }); theMP3.play(); }; $("#play_btn").click(function(){ var thebutton = $(this); if(thebutton.attr("src")=="images/play_button.png"){ thebutton.attr("src","images/play_selected.png"); playSound(); } }).mouseover(function(){ $(this).css("cursor","pointer"); });});

Here we select the play button by using the jQuery selector $("#play_btn"), which selects the element onthe page with the id of “play_btn”.

Page 5: Tutorial

Next we add a .click() method to the button, which will be called when the user clicks on the button. Weset up a variable thebutton equal to $(this) which is the button itself. (This should be familiar if you arecoming from ActionScript.) We then check whether the image’s src attribute is equal to “play_button.png”,and if it is we set it to “play_selected.png”.

Next we call playSound() which tells the MP3 to play. We then add a mouseover() handler to the button,which changes the mouse cursor to a pointer whenever the user moves their mouse over the button. Wehave used a jQuery technique called “chaining” where we have chained the mouseover() function onto the.click() function.

Here are some helpful links to the jQuery documentation to help you understand the .click, .attr,.mouseover and .css methods:

.click()

.attr()

.mouseover()

.css()

If you test the page now, you should be able to press the play button and have the MP3 start playing.

Step 8: Stop Button

In this step we will code the stop button. Add the following code beneath the $("#play_btn").click()function you added above – make sure you add it after the .mouseover() method.

1234567

$("#stop_btn").click(function(){ $("#play_btn").attr("src","images/play_button.png"); $(this).attr("src","images/stop_selected.png"); theMP3.stop();}).mouseover(function(){ $(this).css("cursor","pointer");});

Here we use the same chaining technique as with the play button, adding the .click() and .mouseovermethods to the stop button image. We reset the play button image’s src to “play_button.png”, set the stopbutton image’s src attribute to “stop_selected.png”, and tell the MP3 to stop playing.

You can test this now and should be able to both play and stop the MP3.

Page 6: Tutorial

Step 9: Pause Button

In this step we will code the pause button. Enter the following code beneath the $("#stop_btn").click()method you added in the step above; again, make sure you add it after the .mouseover().

1234567

$("#pause_btn").click(function(){ $("#play_btn").attr("src","images/play_button.png"); $(this).attr("src","images/pause_selected.png"); theMP3.pause();}).mouseover(function(){ $(this).css("cursor","pointer");});

Same methods again: we change the play button image’s src attribute to “play_button.png” and changethe pause button images src to “pause_selected”. We then tell the MP3 to pause.

Step 10: Adding More MP3s

Before we can wire up the forward and back buttons we need more MP3s to play. There are five MP3 filesin the sound folder, and we need a way to access them. We will store the MP3 filenames in an array andaccess them from there. Add the following code along with your other global variables:

1234

private function demonstrate():voidvar theMP3;var currentSong = 0;var tracks = ["1","2","3","4","5"];

The tracks array holds the filenames of the MP3s. I named the MP3′s “1″ through “5″, just to keep it short.

Step 11: createSound() Revised

We will need to change the createSound() method now that we are dealing with multiple MP3s. Edit thecreateSound() as below:

123

theMP3= soundManager.createSound({ id:'sound'+currentSong, url:"../sounds"+tracks[currentSong]+".mp3"

Here we changed the url property to point to the MP3s from the array. Currently currentSong is equal to 0,so it will play the first element in the array – which happens to be called “1.mp3″. When we click on thenext button we will increment currentSong by one, and when we click on the previous button we willdecrement currentSong by one. The playSong() method will be called when we click on either button. Theupcoming code will make this clear.

Step 12: FWD (Forward) Button

Add the following code below the $("#pause_btn") method, as always make sure you put it after themouseover().

123

$("#fwd_btn").click(function(){ if(theMP3 !=undefined){ theMP3.stop();

Page 7: Tutorial

456789

currentSong++; playSound(); } }).mouseover(function(){ $(this).css("cursor","pointer"); });

Here we stop the MP3, increment currentSong, and call playSound(). We first check to make sure thattheMP3 is not undefined before executing any other code. If the user pressed the fwd button without firstpressing play, then theMP3 would have not been instantiated yet. It would throw a JavaScript error, andalthough it would not affect the usage of the app, it as always good to put in preventative measures likethis to make sure your page does not throw any errors.

You should now be able to press the fwd button to make the next song play (you can test it here). Youmight notice that once you go through all five songs it comes to a screeching halt. We will fix this after weget the back button hooked up!

Step 13: Back Button

Add the following code below the $("#fwd_button").click(). As always, make sure you put it underneaththe .mouseover().

123456789

$("#back_btn").click(function(){ if(theMP3 != undefined){ theMP3.stop(); currentSong--; playSound(); }}).mouseover(function(){ $(this).css("cursor","pointer");});

This is nearly identical to the code we added in the step above. All we are doing differently is decreasingthe currentSong variable by 1. Again, if you try it out, you’ll notice that if you go below the number ofsongs available nothing happens. Let’s fix this in the next step.

Step 14: Fixing the FWD and BACK Buttons

Add the following code directly beneath the playSound() function.

1234567

function playSound(){ if(currentSong>=tracks.length){ currentSong=0; } if(currentSong<0){ currentSong = tracks.length-1; }

What we are doing here is making sure we keep the currentSong variable within the bounds of our array. IfcurrentSong is greater than the length of our array, we need to set it to 0. If currentSong is less than 0 weset it to one less than the array’s length – that is, to the last element in the array.

Using this method, when we reach either end of the array we wrap back around, making a nice forwardand back system for our MP3 player.

Step 15: Volume Control

Page 8: Tutorial

In this step we will wire up the volume control for our MP3 player. Add the following code beneath the$("#back_btn").click(). Make sure you put it beneath the mouseover().

01020304050607080910111213

$("#volumebar").mousemove(function(e){ var parentOffset = $(this).parent().offset(); var relX = Math.floor(e.pageX - parentOffset.left); var vol = Math.ceil( (relX-7)/10)-4; if(vol >=1 && vol <=10){ $(this).attr("src","images/vb"+vol+".png"); if (theMP3 != undefined){ theMP3.setVolume(vol*10) } }}).mouseover(function(){ $(this).css("cursor","pointer");});

This code might look a bit confusing, but we will break it down bit by bit.

Notice we have used mousemove(), so the code inside will be called as the user moves their mouse over thevolume bar, without them needing to click. The first thing we do is get the offset of the $("#volumebar")‘sparent, which in this case is the #player div. You can verify this by adding the following code:

1alert($(this).parent().attr("id"));

…or by referring to this image again:

The .offset() method allows us to retrieve the current position of an element relative to the document.Here we get the offset of the #player div, and in the next line of code we set a variable relX equal to(e.pageX - parentOffset.left). What we are doing here is making sure when we mouseover #volumebarthat we are getting the coordinates of the #volume bar itself (within the MP3 player). If we had not donethe above math, then the coordinates would have included the parent offset, and would throw off anycalculation if you decided to move the MP3 player to a new location in the page.

(I am assuming you are using a modern browser that allows you to log values. The FireBug plugin inFireFox works quite nice for this. If you are on Chrome then select Tools > Developer Tools and click onthe Console tab.)

If you want to see what the parentOffset is, add the following below the var parentOffset =$(this).parent().offset():

Page 9: Tutorial

1console.log(parentOffset);

When I ran this in my browser it was around 326px with a few decimal places. Yours may read outdifferently depending on what your screen resolution is. Below is an image that shows the parentOffset inFireFox.

In the next section we are calculating a number between 1 and 10. This may look really confusing but wewill break it down bit by bit again.

Comment out the line var vol = Math.ceil( (relX-7/10)-4), add the following code and test:

010203040506070809101112131415

$("#volumebar").mousemove(function(e){ var parentOffset = $(this).parent().offset(); var relX = Math.floor(e.pageX - parentOffset.left); //var vol = Math.ceil( (relX-7)/10)-4; var vol = Math.ceil( (relX)); console.log(vol); if(vol >=1 && vol <=10){ $(this).attr("src","images/vb"+vol+".png"); if(theMP3 != undefined){ theMP3.setVolume(vol*10) } }}).mouseover(function(){ $(this).css("cursor","pointer");});

Now try to position your mouse cursor just between some of the dots. You should get a number like 57,87,or 117 depending on where you place the cursor. Below is an image showing this.

Next add the following code.

01020304050607

$("#volumebar").mousemove(function(e){ var parentOffset = $(this).parent().offset(); var relX = Math.floor(e.pageX - parentOffset.left); //var vol = Math.ceil( (relX-7)/10)-4; var vol = Math.ceil(relX-7); console.log(vol); if(vol >=1 && vol <=10){

Page 10: Tutorial

0809101112131415

$(this).attr("src","images/vb"+vol+".png"); if(theMP3 != undefined){ theMP3.setVolume(vol*10) } }}).mouseover(function(){ $(this).css("cursor","pointer");});

Now you should be getting a whole number like 50, 80, 110. Again here is an image showing the changes.

Add the following code.

010203040506070809101112131415

$("#volumebar").mousemove(function(e){ var parentOffset = $(this).parent().offset(); var relX = Math.floor(e.pageX - parentOffset.left); //var vol = Math.ceil( (relX-7)/10)-4; var vol = Math.ceil( (relX-7)/10); console.log(vol); if(vol >=1 && vol <=10){ $(this).attr("src","images/vb"+vol+".png"); if(theMP3 != undefined){ theMP3.setVolume(vol*10) } }}).mouseover(function(){ $(this).css("cursor","pointer");});

Getting closer – we are now logging small whole numbers. Below is an image.

You’ll notice the second circle logs 6 when between the circles it should equate to 2 for the volume. Seemswe are still off by 4, so we subtract 4 and viola we arive at the correct number! Hence the following code:

01020304

$("#volumebar").mousemove(function(e){ var parentOffset = $(this).parent().offset(); var relX = Math.floor(e.pageX - parentOffset.left); var vol = Math.ceil( (relX-7)/10)-4;

Page 11: Tutorial

05060708091011121314

console.log(vol); if(vol >=1 && vol <=10){ $(this).attr("src","images/vb"+vol+".png"); if(theMP3 != undefined){ theMP3.setVolume(vol*10) } }}).mouseover(function(){ $(this).css("cursor","pointer");});

Below is an image that show the result of the final calculation:

Now that we have the correct numbers, we check whether the vol is between 1 and 10. If it is, we set the#volumebar‘s “src” attribute to one of the 10 images of the volume bar that is in the images folder. Forexample, if vol was equal to 5 then "images/vb"+vol+".png" would translate into “images/vb5.png”. Belowis an image of “vb5.png” to help make this clear.

Finally, we make sure that theMP3 is not undefined, and if it isn’t we set the volume on it using (vol*10)which would equal somewhere between 10 – 100, depending on what value vol happens to be.

Step 16: Progress Bar

In this step we will tie in the Progress Bar. In the HTML source, there is a div with an id of #progressbar.To turn this div into a Progress Bar we call jQuery UI’s .progressbar() method on it like so:

1$( "#progressbar" ).progressbar();

Add the following code within $(document).ready().

123456789

$(document).ready(function() { soundManager.url = 'swf'; soundManager.flashVersion = 8; var theMP3; var currentSong =0; var tracks = ["1","2","3","4","5"]; $( "#progressbar" ).progressbar({ value: 50 });

Now refresh the page and you should see the Progress Bar at 50%. Okay, now set the value to zero.

123

$( "#progressbar" ).progressbar({ value: 0});

Page 12: Tutorial

SoundManager has a whilePlaying() method that is called repeatedly while the sound is playing, and thisis where we will update our Progress Bar. Add the following code within createSound().

010203040506070809101112

theMP3= soundManager.createSound({ id:'sound'+currentSong, url:"../sounds/"+tracks[currentSong]+".mp3", whileplaying:function(){ duration = this.duration; pos = this.position; songPosition = (pos/duration)*100; console.log("Pos/Duration " + pos/duration); console.log("Song Position " + songPosition); } });

Make sure you add the comma after url:"../sounds/"+tracks[currentSong]+".mp3". Here we set durationequal to the song’s duration, and pos equal to the current position within the song’s. We then figure out thesongPosition percentage by dividing pos by duration and multiplying by 100. Finally, we log the values sowe can see what they equate to.

We now have a number in the variable songPosition that we can use with our Progress Bar. Add thefollowing code:

123456

whileplaying:function(){ duration = this.duration; pos = this.position; songPosition = (pos/duration)*100; $( "#progressbar" ).progressbar( "option", "value", songPosition);}

Here we are setting the Progress Bar’s value to songPosition which will always be a number between 1 and100. You will notice if you switch to a new song that the Progress Bar “resets” itself.

Step 17: Song Position

In this step we will tie in the time display. In the HTML there is a div with the id #time, and this is wherewe will insert the time display of the current MP3. Like the Progress Bar we will calculate this within thewhileplaying() method.

Add the following code within whileplaying():

01020304050607080910111213141516

whileplaying:function(){ duration = this.duration; pos = this.position; songPosition = (pos/duration)*100; $( "#progressbar" ).progressbar( "option", "value", songPosition); var time = pos/1000; console.log("Time " + time); var min = Math.floor(time/60); console.log("Min" + min); var minDisplay = (min<10) ? "0"+min : min; var sec = Math.floor(time%60); console.log("Sec " + sec); var secDisplay = (sec<10) ? "0"+sec : sec; var amountPlayed = minDisplay+":"+secDisplay;}

Here we set up our time variable. Since pos is in milliseconds we divide by 1000 to get a number inseconds, such as 2.038, 10.998 etc. We then set a variable min equal to Math.floor(time/60) to give usour minutes. Next, we set up a variable minDisplay to format the number; if min is less than 10 we add a 0

Page 13: Tutorial

in front of it (as a string), otherwise we just leave it alone.

Next we set up a variable sec which is equal to Math.floor(time%60); here we are using the modulooperator which returns the remainder of a division, so in this case it is returning the remainder of time/60,which is the number of seconds through the current minute. We set our secDisplay variable up the sameway we did the minDisplay variable: if sec is less than 10 we add a zero to it, otherwise we leave it as is.

Finally we set up a variable amountPlayed which shows the minDisplay and secDisplay with a colon inbetween them, like 1:30. (In case any of this is unclear, we are logging the values to help you understand.)

Now change the above code to the following:

12345678

var time = pos/1000;var min = Math.floor(time/60);var minDisplay = (min<10) ? "0"+min : min;var sec = Math.floor(time%60);var secDisplay = (sec<10) ? "0"+sec : sec;var amountPlayed = minDisplay+":"+secDisplay; $("#time").text(amountPlayed);

Notice that I removed all the console.log calls, because it affected the performance of the time updating –it would only update every 2-3 seconds. Logging so much information at once seriously affectsperformance. Remember this when you put your apps live!

Step 18: Song Duration

In this step we will set up the duration part of the time display. Add the following code, below the code youadded above:

123456

var timeduration = duration/1000;var minduration = Math.floor(timeduration/60);var minDisplay = (minduration<10) ? "0"+minduration : minduration;var secduration = Math.floor(timeduration%60);var secDisplay = (secduration<10) ? "0"+secduration : secduration;var totalDuration = minDisplay+":"+secDisplay;

Here we are using the same method to calculate the duration as we did with the time in the step above.The only thing that is different is we are dividing duration/1000, instead of pos/1000.

Now move the $("#time").text(amountPlayed) below the line var totalDuration =minduration+":"+secduration and change it to the following:

1$("#time").text(amountPlayed + " / " + totalDuration);

Here we are displaying both the amountPlayed and totalDuration, separated by a slash.

Here is the all the code from these last two steps:

01020304050607080910111213

var time = pos/1000;var min = Math.floor(time/60);var minDisplay = (min<10) ? "0"+min : min;var sec = Math.floor(time%60);var secDisplay = (sec<10) ? "0"+sec : sec;var amountPlayed = minDisplay+":"+secDisplay; var timeduration = duration/1000;var minduration = Math.floor(timeduration/60);var minDisplay = (minduration<10) ? "0"+minduration : minduration;var secduration = Math.floor(timeduration%60);var secDisplay = (secduration<10) ? "0"+secduration : secduration;var totalDuration = minDisplay+":"+secDisplay;

Page 14: Tutorial

1415

$("#time").text(amountPlayed +" / "+totalDuration)

If you test now, you should see both the current time and total duration displayed.

Step 19: Getting the ID3 information

In this step we will get the ID3 information from the MP3s. SoundManager has an onid3() method that isfired off once the ID3 information from the MP3 is available. In testing I found that the the onid3() methodonly fires one time per song, so we need a way to cache the ID3s. We will use an array to accomplish this.

Add the following within $(document).ready().

1234567

$(document).ready(function() { soundManager.url = 'swf'; soundManager.flashVersion = 8; var theMP3; var currentSong =0; var tracks = ["1","2","3","4","5"]; var id3s=[];

Now below the whileplaying() method you added in the steps above, add the following code.

01020304050607080910111213

whileplaying:function(){ duration = this.duration; pos = this.position; songPosition = (pos/duration)*100; //...... //......},onid3: function() { artist = this.id3["TPE1"]; title = this.id3["TIT2"]; id3s.push({theArtist:artist,theTitle:title}); console.log("Artist " + artist + " Title " + title);}

Make sure you add a comma after the closing brace of the whileplaying() method as shown above.

Here we are getting the ID3 information for the artist and the title of the song, and pushing them into theid3s array. A good reference for the ID3 tags can be found on Wikipedia; we are using ID3v2. Finally weare logging the values, as usual.

If you test now you whould see the artist and title of the song logged in the console.

Step 20: Displaying ID3 info

Now that we have the ID3 info, we will display it. In the HTML there is a div named #scroller_container,and within this div there is a div named #scroller with a p tag inside. This p tag is where we will insertthe ID3 information. Add the following code within the onid3() method.

123

if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " + id3s[currentSong]["theTitle"]);}

Here we make sure that the id3s[currentSong] !=undefined for good housekeeping measures, and if it isnot then we set the $("#scroller p") text to the current song’s ID3 information.

Page 15: Tutorial

You can test now and should see the ID3 information being displayed. It is not moving yet, and the textextends beyond the div, but we will fix that in the following steps.

Step 21: Using the jScroller Plugin

The jScroller plugin allows us to make the text scroll along within a div. We will be wiring up the jScrollerplugin in this step.

Before we can use the jScroller plugin we need to set it up. Add the following within $(document).ready():

01020304050607080910

$(document).ready(function() { soundManager.url = 'swf'; soundManager.flashVersion = 8; var theMP3; var currentSong =0; var tracks = ["1","2","3","4","5"]; var id3s=[]; $jScroller.add("#scroller_container","#scroller","left",2); $jScroller.cache.init = true; // Turn off default Event $jScroller.config.refresh = 100;

Here we are initializing the jScroller plugin, by passing the two divs to it and setting the direction andspeed. We set the cache.init property to true, which disables the default events, and set theconfig.refresh to 100 milliseconds, which determines how frequently it refreshes the display.

By default the Autoscroller will stop when you leave the window or the document and start again when youaccess the window or document again. In some cases it could be that you want to stop the Scroller withthese Default Events, so you can turn them off with $jScroller.cache.init.

If you test now you will see the text does not extend beyond the div any more. So with that fixed, let’s getit moving!

Add the following code changes within the onid3 method:

0102030405060708091011

onid3: function() { artist = this.id3["TPE1"]; title = this.id3["TIT2"]; id3s.push({theArtist:artist,theTitle:title}); $jScroller.stop(); if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " +id3s[currentSong]["theTitle"] ); } var t=setTimeout(startScroller,2000); }

Here we are stopping the jScroller by calling jScroller.stop(). We then usesetTimeout(startScroller,2000), which waits two seconds then calls the startScroller() function whichwe will code next. This gives a short delay between the time the text shows and starts moving.

Add the following within $(document).ready()

0102030405060708091011

$(document).ready(function() { soundManager.url = 'swf'; soundManager.flashVersion = 8; // ...... // ...... $( "#progressbar" ).progressbar({ value: 0 }); function startScroller(){ $jScroller.start(); }

Page 16: Tutorial

Here we are just telling the jScroller plugin to start.

Now if you test, the text starts scrolling after two seconds. You will notice when you change songs that thetext just changes no matter where it is at; if it is halfway across then the new text shows up halfwayacross. This looks quite bad, but we will fix it in the next step.

Step 22: Modifying the jScroller plugin

The jScroller plugin does not have a method to reset itself, but we can get the source code and add ourown reset functionality. You can grab the source from Google Code. Once you have downloaded thisJavaScript file, put it in the “js” folder. You will also need to update the HTML file to point to this file fromnow on.

12345

<script type="text/javascript" src="js/jquery-1.7.1.min.js"></script><script type="text/javascript" src="js/jquery-ui-1.8.17.custom.min.js"></script><script type="text/javascript" src="js/jscroller-0.4-src.js"></script><script src="js/soundmanager2-jsmin.js"></script><script type="text/javascript" src="js/mp3player.js"></script>

Now open the jScroller src file you just downloaded, and add the following after pause:function():

01020304050607080910111213

private function demonstrate():voidpause: function(obj,status) { if (obj && typeof status !== 'undefined') { for (var i in $jScroller.config.obj) { if ($jScroller.config.obj[i].child.attr("id") === obj.attr("id")) { $jScroller.config.obj[i].pause = status; } } }},reset: function(){ $jScroller.config.obj=[];},

What we are doing here is clearing out the config.obj. Then all we have to do is instaintiate a new$jScroller object. This will become clear in the code below.

Add the following within the onid3() method.

010203040506070809101112

onid3: function() { artist = this.id3["TPE1"]; title = this.id3["TIT2"]; id3s.push({theArtist:artist,theTitle:title}); $jScroller.stop(); if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " +id3s[currentSong]["theTitle"] ); } $jScroller.reset(); $jScroller.add("#scroller_container","#scroller","left",2); var t=setTimeout(startScroller,2000);}

As you can see we call our newly created $jScroller.reset() function, and since we cleared everythingout, we need to create a new $jScroller by calling$jScroller.add("#scroller_container","#scroller","left",2).

If you test now you will see the text resets itself – no more changing halfway through. Pretty sweet, eh?

Page 17: Tutorial

Step 23: Stopping the $jScroller

Whenever we press the stop button the text keeps scrolling. It would be nice to make the text stop as well.Add the following code to the $("#stop_btn").click().

12345678

$("#stop_btn").click(function(){ theMP3.stop(); $jScroller.stop(); $("#play_btn").attr("src","images/play_button.png"); $(this).attr("src","images/stop_selected.png");}).mouseover(function(){ $(this).css("cursor","pointer");});

While we are here, let’s do the same thing for the pause button. Add the following code to$("#pause_btn").click():

12345678

$("#pause_btn").click(function(){ $("#play_btn").attr("src","images/play_button.png"); $(this).attr("src","images/pause_selected.png"); theMP3.pause(); $jScroller.stop();}).mouseover(function(){ $(this).css("cursor","pointer");});

That’s all well and good, but now we need to start again when we press play. We do this in the next step.

Step 24: Starting the $jScroller

This is easy enough. Add the following code to the $("#play_btn").click():

01020304050607080910

$("#play_btn").click(function(){ var thebutton = $(this); if(thebutton.attr("src")=="images/play_button.png"){ thebutton.attr("src","images/play_selected.png"); playSound(); $jScroller.start(); }}).mouseover(function(){ $(this).css("cursor","pointer");});

Test it out here.

Step 25: Continous Play

As of right now when a song ends we have to press the forward button to go to the next song. It would benice to have the MP3 player automatically advance. That is just what we will do in this step.

SoundManager has an onfinish() function that gets called when the current song finishes playing. Add thefollowing code beneath the onid3 function:

01020304050607

onid3: function() { artist = this.id3["TPE1"]; title = this.id3["TIT2"]; id3s.push({theArtist:artist,theTitle:title}); $jScroller.stop(); if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " +id3s[currentSong]["theTitle"] );

Page 18: Tutorial

0809101112131415161718192021222324252627

} $jScroller.reset(); $jScroller.add("#scroller_container","#scroller","left",2); var t=setTimeout(startScroller,2000);},onfinish:function() { currentSong++; playSound(); $jScroller.stop(); if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " +id3s[currentSong]["theTitle"] ); } $jScroller.reset(); $jScroller.add("#scroller_container","#scroller","left",2); var t=setTimeout(startScroller,2000); alert(id3s[currentSong]["theTitle"]); }

Make sure you add the comma after the closing brace of the onid3 function.

Here all we are doing is incrementing the currentSong variable and calling playSound(). You will notice thatit uses the same logic that the onid3() function uses to reset() and add() a new $jScroller. The reasonwe have to do it in the finish() function as well as the onid3() function, is that onid3() only gets calledonce for each song. If we happen to go through all the songs without this code here, then text would notchange on the next round. This is why we made the id3s array, so we could have a cache of the artist andtitle.

Now if you test and let the songs play all the way through it should advance to the next songautomatically.

Step 26: Forward and Back Buttons

Now that we are playing through all the songs, pressing the forward and back buttons presents the sameproblem the onfinish() function had. Since we went through all the songs we need to pull in the ID3s fromthe id3s array. So once again we will use the same code.

This is starting to get a bit messy, so lets create a function that contains the relevant code. Add thefollowing above the startScroller() function:

01020304050607080910111213

function updateArtist(){ $jScroller.stop(); if(id3s[currentSong] !=undefined){ $("#scroller p").text(id3s[currentSong]["theArtist"] + " : " +id3s[currentSong]["theTitle"] ); } $jScroller.reset(); $jScroller.add("#scroller_container","#scroller","left",2); var t=setTimeout(startScroller,2000);}function startScroller(){ $jScroller.start();}

We have seen this code a few times by now, so there is no need to explain it. All we need to do is add it tothe forward and back buttons. Add the following code in the $("#fwd_btn").click():

0102030405

$("#fwd_btn").click(function(){ if(theMP3 !=undefined){ theMP3.stop(); currentSong++; playSound();

Page 19: Tutorial

0607080910

updateArtist() }}).mouseover(function(){ $(this).css("cursor","pointer");});

And add the following within the $("#back_btn").click().

01020304050607080910

$("#back_btn").click(function(){ if(theMP3 != undefined){ theMP3.stop(); currentSong--; playSound(); updateArtist(); }}).mouseover(function(){ $(this).css("cursor","pointer");});

Now if you test the forward and back buttons they should change the text as well.

Step 27:Clean up onid3() and onfinish

Now that we have made the updateArtist() function, let’s go back and remove all that unnecessary codefrom the onid3() and onfinish() functions. Change the onid3() function to the following:

123456

onid3: function() { artist = this.id3["TPE1"]; title = this.id3["TIT2"]; id3s.push({theArtist:artist,theTitle:title}); updateArtist();},

And change the onfinish() function as follows.

12345

onfinish:function() { currentSong++; playSound(); updateArtist();}

That is much better.

Step 28: Your Homework

Right now, if you press the pause or stop button, their images change to the selected image. But when youpress play again they do not change back to the regular image. Make it so when you press play, the pauseand stop buttons change back to the “unselected” image.

Conclusion

Using SoundManager 2 we have coded a sweet little JavaScript MP3 Player. I could have used HTML5Audio, but we would have lost the ID3 functionality, and so would have had to hard-code all of our artistsand titles. SoundManager automatically uses HTML5 Audio for the iDevices (iPhone, iPod, iPad), so if youare looking for a JavaScript sound library to use for your HTML5 iPad apps, maybe you should considerSoundManager.

Page 20: Tutorial

I hope you’ve found this tutorial helpful, and thanks for reading!

James Tyner

James Tyner loves to program in all kinds of languages during the day.At night he spends his time playingsemi-professional guitar with his band.When he’s not programming or playing guitar he can be found at thelocal Starbucks sipping on a Venti Coffee and reading a good book.

See more content from this author →