JavaScript media player

Download JavaScript Media PlayerA while back I was impressed to see the Yahoo Media Player, which can be used to stream mp3s on a website. It appeared on the face of it to be a JavaScript only browser media player, which seemed not only impressive, but impossible. As it turned out, the media player actually used flash underneath the hood by making a series of API calls without the need for the typical flash UI.

Being suitably impressed I decided to write my own – I wanted several distinct features like a playlist and a custom look. I then found an astonishing good JavaScript API that interfaced to the audio features in Flash. This library was called SoundManager2, check it out, it’s great. SoundManager does provide some neat demo applications, but nothing that matched my needs – incidentally the demos may be far better now as I wrote this code almost a year ago.

So what was I looking to achieve with this:

  1. I wanted to queue tracks in a playlist;
  2. The order of the playlist must be dynamic, i.e. you can drag and drop the tracks to change their order;
  3. Adding the media player to a website is as easy as adding a div with a specific id attribute;
  4. Adding items to a playlist must be as simple as including an anchor tag with a specific CSS class;
  5. The colours, dimensions, and images should be easily overridable but also have sensible defaults;
  6. The path to the library should be configurable in some manner.

So what did this turn out like? Well you can see it in action on www.feellikefalling.com. I encourage you to check it out to see things like the play list drag and drop etc in action. Update: I have embedded the player here so that you don’t need to navigate away if you don’t want to.

So if you want to include this on your website how to you do it? It’s pretty easy – you don’t need to be a web developer! First you need to download all the required files by clicking the big button above or here, extract the files, and then upload the these files to your web server. The HTML required to embed the player is minimal and is show below:

1
2
3
4
5
6
7
8
9
10
11
12
<div id="myplayer"> 
  <a class="myplayer_mp3" href="song1.mp3" 
     title = "Feel Like Falling - Can't Rock With The Kids">
      <span class="myplayer_artist">Feel Like Falling</span> - 
      <span class="myplayer_song">Can't Rock With The Kids</span>
  </a>
  <a class="myplayer_mp3" href="song2.mp3"
     title = "Feel Like Falling - Purple T">
      <span class="myplayer_artist">Feel Like Falling</span> -
      <span class="myplayer_song">Purple T</span>
  </a>
</div>

To include the website media player in the page you simply add a div element with id myplayer. Then to add an mp3 to the playlist you create an anchor (a) tag with class myplayer_mp3. To include a tooltip for the song you simply add a title attribute to the a element. So what we are doing is creating a playlist from a series of urls specified in the a tags, it’s as simple as that.

In order to get all this to work you need to include the following in your document header:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<link rel="stylesheet" type="text/css" href="js/myplayer/player.css">
 
<!--You must specify the location, relative to this file, where
    the myplayer source can be found. This allows it to set up
    some things automatically for you -->
<script type="text/javascript" charset="utf-8">
  var _MyPlayerLocation_ = "js/myplayer";
 </script>
 
<!-- It uses jQuery so load the main jQuery library however 
     you wish in this case I'm using Google to host it -->
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  google.load("jquery", "1.3.2");
 </script>
 
<!--The rest are JavaScript file that are required by the media
    player and should be included in the order specified - they 
    are all contained in the downloadable zip file. All you have 
    to do is make sure you have specified the correct path
    relative to this file -->
 <script type="text/javascript"
          src="js/myplayer/jquery/jquery-ui-custom.min.js"></script>
 <script type="text/javascript"
          src="js/myplayer/jquery/jquery.tooltip.js"></script>        
 <script type="text/javascript"
          src="js/myplayer/soundmanager/soundmanager2-min.js"></script>
 <script type="text/javascript"
          src="js/myplayer/utils.js"></script>
 <script type="text/javascript"
          src="js/myplayer/myplayer.min.js"></script>

Instead of explaining all of the above I suggest you just take a look at the inline comments. There is also a sample HTML file in the downloadable zip containing full working example – apart from the actual mp3 sound files.

You can also customise the player visually with relative ease. The colour scheme can be changed by simply overriding the default CSS styles for the player. For example, consider the following screenshot:

Customised Media Player

Here the volume bars, the play timer, the currently playing song background, and main background colour have all been changed. The code below shows the CSS elements that had to be changed/created to achieve this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div#myplayer { background-color: #696969; height: 25em; }
 
#myplayer_playlist_container { height: 20em; }
 
div#myplayer_playing_timer { background-color: #6D0D33; }
 
div.myplayer_strip_skin_on { background-color: #6D0D33; }
 
#myplayer_playlist li { background-color: #929292; color: #FFFFFF; }
 
a.myplayer_mp3 { color: #000000;	}
 
#myplayer_playlist li.ui-selected { background-color: #6D0D33; }
 
#myplayer_playlist li.ui-selected a { color: #FFFFFF; }

Hopefully the method of skinning the player, as shown above, is straightforward to understand, it’s just basic CSS. Obviously just about anything can be customised through the use of CSS, and I suggest taking a look at the generated HTML to identify the appropriate ids and classes – you can use firebug HTML explorer with Firefox (or the equivalent in IE, Chrome, Safari, etc). In fact, the HTML generated can also be modified easily – take a look at the myplayer_snippets.js to do this. Be aware though that some of the elements generated are essential to the working of the application though.

For those more artistically inclined than me feel free to give it a sweeping new skin – in the colours of the site I linked to so that I can get the benefits 😉

It goes without saying there will be bugs! If you find any, either leave a comment or better still email me – my address can be found in the about section of this site.

So feel free to add the webpage media player to your site! Enjoy.Download JavaScript Media Player

the curious case of the graphical interface

Until recently I had a rather nescient attitude to the needs of users who have barely seen a computer never mind used one. It’s easy for developers to forget about these people. However they exist, and with the rise of the internet as the dominant carrier of information, I would presume that now more than ever the new computer user is finding their way online.

Most developers have had the “keep it simple” mantra for UI development drilled into them over the years, both in an academic and commercial setting. However, having spent some time educating a few older family members (who fall into the computer newbie category described above) on the ways of the internet, I’m of the impression that it’s not just simplicity that is required but moreover consistency.

For example. A simple hyperlink like this one which seems innocuous to the average user, can cause trouble. Why? Well, when “teaching” people to use the internet it’s helpful if you can define some simple rules. One of these rules might be “Things you can click on will be underlined”. Rules like this give a surprising amount of comfort to an inexperienced computer user. However, until actually watching a family member struggle when links are not underlined I would not have known/believed the problem existed. To them the link above just looks like a piece of coloured text, which they don’t associate with the simple rule. A similar situation occurs when links are in the form of an image, where unless it looks like a button then they are unlikely to click it.

However, many sites don’t underline hyperlinks, so an alternative rule may be “When you move your mouse over a piece of text and it turns into a little hand, then you can click it”. That is as long as someone has not change the default cursor – thank you for this feature Internet Explorer! This rule is not ideal though as means you have to trawl the entire page to find links.

If you plan to really confuse a new user then you can always do the following: fail to underline the text, have it the same colour as the rest of the text, and instead of using an anchor tag, use any tag you like and just assign an onclick handler to the element in javascript. That way you get no cursor that changes to the familar hand as well. Awesome.

The above problem really does exist and I have seen it on many websites even those undertaken by well known web agencies.

This is not the only area of inconsistency, there are many others. In fact, another problem that seemed to cause increased stress levels is time/date input – for example a flight search engine. Most sites that require this functionality tend to provide some sort of calendar widget. Therefore, you can show someone how to input a date by asking them to first click on the calendar image, now click the appropriate button to navigate to the required month, then click on the required day to select. However, every calendar widget is slightly different which is just the start of the confusion. The real problem is reserved for those sites that do not have a calendar widget to select the date. The user then looks everywhere trying to find this calendar button to click, and finally is left pondering the date format to enter manually – if they even get this far. Surely it must be to the benefit of everyone if we agree on a standard calendar widget that can be skinned in some way? Just a thought.

I’m sure there are many other areas where this sort of confusion can occur – I can only begin to imagine the problems with Flash sites! Hence the next time you are designing a webpage that is intended for public consumption it’s probably worth bearing this in mind.

the problem with frameworks

I love frameworks. You love frameworks. We ALL love frameworks. As web developers we just can’t get enough of these things. They’re everywhere: from Rails, to MS MVC, to CakePHP, to Django, and so on. I’m so obssessed with frameworks that I spend more time thinking about what one to use than actually using it. But this is not the only problem, as after choosing one, your problems can really start.

On a project that I have been intermitently working on for a little while now I chose to use CakePHP. The reason for this choice? Well first, I had a pretty good knowledge of PHP as I wrote my own little PHP framework when web frameworks were a mere twingle in their daddies eyes. Second, PHP is widely supported on shared hosting – though Ruby is catching up (that said, I’ve experienced some horrors with Ruby hosting). The widespread availability of PHP also means that PHP hosting tends to be cheaper.

Anyway, this is all beside the point. My real issue is with the size and complexity of these frameworks. Just the other day I was looking to do something as simple as validate an input that was supplied as an HTML POST parameter. Pretty simple right? Well it ended up taking me a disproportionate amount of time to do this task.

The first port of call was to find out if the framework itself supported this, which to my delight CakePHP (1.2) delivered on. Now it was down to the trawl/skim through the documentation trying to figure out how to actually do it. I found what I presumed done the task – basically I was required to add the appropriate validation rules to my model. Thus I added the following:

1
2
3
4
5
6
7
8
9
<?php
class Section extends AppModel {
    var $name = 'Section';
    var $actsAs = array('Tree');
    var $validate = array( 'name' => array('rule' => alphaNumeric,
                                           'required' => false,
                                           'message' => 'Alpha numerics only'));
}
?>

Then in my controller I simply called the validate method:

1
2
3
4
if(!$this->Section->validates()) {
    parent::handleAJAXError($this->Section->validationErrors);
    return;
}

What happened? NOTHING! I passed data that should have failed and it passed. SHIT! I then decided to check to see that the rules were getting parsed so changed the required key in the rules to true, and passed nothing in. Now it worked – it asked me to specify the parameter. My logic was therefore it can see the data and the rules are getting parsed so what the hell is happening!

By this point I had spent quite some time trying to figure this all out. To be honest, I could have written the validation code quicker. So that’s what I decided to do. Yes I reinvented the wheel, it took me around 5 mins, dwarfing the hours I had spent trying to get the stupid library validation code to work. Not only that, much of the supposed benefits offered by using the built in validation code was of no use to me – it wasn’t built around AJAX requests. So what is the moral of this story?

Well it’s read the documentation better, don’t run the most stupid tests, and don’t charge-in thinking you know how everything works! WHAT I hear you say?!

If only I had taken more care when reading, eh the first paragraph, in the documentation I would have observed this:

First, set the data to the model:

$this->ModelName->set( $this->data );

Whoops I never done this. Basically I wasn’t EVER passing in any data to validate, which makes my shocking test of changing the required to true to convince myself the rules and data were being parsed an absolute joke. Rushing in to write my hand crafted code is as bad as the other old chestnut of complaining “there is a bug in the compiler” – c’mon we have all said it 😉 The only thing I can credit myself with here is that after a recent 4 week holiday I was stubborn enough to not give up and go back an look at it. Therefore, if there is anything to learn from this experience it’s that before starting something make sure you have taken the time to either read the documentation or listen to those trying to guide you. Oh and have a certain amount of stubbornness about you – not too much though.