Seeking works in firefox
authorJoar Wandborg <git@wandborg.com>
Thu, 29 Mar 2012 14:06:36 +0000 (16:06 +0200)
committerJoar Wandborg <git@wandborg.com>
Thu, 29 Mar 2012 14:06:36 +0000 (16:06 +0200)
- Added support for indicating multiple buffered
  ranges (Firefox)
- Added volume slider (Chromium)
- Replaced stop button with faux pause button
- Added 'ended' event handler

mediagoblin/static/css/audio.css
mediagoblin/static/js/audio.js

index 5f7a888aefa135b7b2962dceb88f72ca61a4b5e9..387278ec8095fe00128ebf18d10528c6e2c1e622 100644 (file)
@@ -10,6 +10,7 @@
     height: 100%;
     -webkit-transition: width .1s ease-out;
     -moz-transition: width .1s ease-out;
+    transition: width .1s ease-out;
 }
 .audio-control-play-pause {
     position: absolute;
 }
     .audio-control-play-pause.playing {
         color: #b71500;
+        letter-spacing: -17px;
+        margin-left: -7px;
     }
     .audio-control-play-pause.paused {
+        /* Warning: this means the the play button shows! */
         color: rgb(134, 212, 177);
     }
-.buffered {
+
+.buffered-indicators {
     position: absolute;
     bottom: 0;
     left: 0;
     height: 2px;
-    width: 0;
-    -webkit-transition: width 1s ease-out;
-    -moz-transition: width 1s ease-out;
-    background: rgba(134, 177, 212, 1);
-    cursor: pointer;
 }
+    .buffered-indicators div {
+        position: absolute;
+        height: 2px;
+        left: 0;
+        background: rgba(134, 177, 212, 1);
+
+        -webkit-transition: left 1s ease-out;
+        -moz-transition: left 1s ease-out;
+        transition: left 1s ease-out;
+
+        -webkit-transition: width 1s ease-out;
+        -moz-transition: width 1s ease-out;
+        transition: width 1s ease-out;
+
+        cursor: pointer;
+    }
+
 .seekbar {
     position: absolute;
     top: 0;
     width: 100%;
     height: 100%;
 }
+
 .audio-currentTime {
     position: absolute;
     bottom: 0;
     right: 0;
     background: rgba(0, 0, 0, 0.7);
 }
+
+.audio-volume {
+    position: absolute;
+    left: 50px;
+    bottom: 10px;
+    opacity: 0.3;
+    -moz-transition: opacity .1s ease-in-out;
+    -webkit-transition: opacity .1s ease-in-out;
+    transition: opacity .1s ease-in-out;
+}
+    .audio-spectrogram:hover .audio-volume {
+        opacity: 1;
+    }
index 91d52f960df9e95f306a5fb9f19ba285a17a6959..f50908a131b733f7e2080e7c137533cc7daeae4b 100644 (file)
@@ -21,46 +21,110 @@ var audioPlayer = new Object();
 (function (audioPlayer) {
     audioPlayer.init = function (audioElement) {
         audioPlayer.audioElement = audioElement;
+
         console.log(audioElement);
+
         attachEvents();
+
         $(audioElement).hide();
     };
 
     function attachEvents () {
-        audioPlayer.audioElement.addEventListener('durationchange', audioPlayer.durationChange, true);
-        audioPlayer.audioElement.addEventListener('timeupdate', audioPlayer.timeUpdate, true);
-        audioPlayer.audioElement.addEventListener('progress', audioPlayer.onProgress, true);
+        audioPlayer.audioElement.addEventListener(
+            'durationchange', audioPlayer.durationChange, true);
+        audioPlayer.audioElement.addEventListener(
+            'timeupdate', audioPlayer.timeUpdate, true);
+        audioPlayer.audioElement.addEventListener(
+            'progress', audioPlayer.onProgress, true);
+        audioPlayer.audioElement.addEventListener(
+            'ended', audioPlayer.onEnded, true);
+
         $(document).ready( function () {
-            $('.audio-spectrogram').delegate('.seekbar', 'click', audioPlayer.onSeek);
-            $('.audio-spectrogram').delegate('.audio-control-play-pause', 'click', audioPlayer.playPause);
+            $('.audio-spectrogram').delegate(
+                '.seekbar', 'click', audioPlayer.onSeek);
+            $('.audio-spectrogram').delegate(
+                '.audio-control-play-pause', 'click', audioPlayer.playPause);
+            $('.audio-spectrogram').delegate(
+                '.audio-volume', 'change', audioPlayer.onVolumeChange);
+            $('.audio-media').delegate(
+                '.audio-spectrogram', 'attachedControls',
+                audioPlayer.onControlsAttached);
         });
     }
 
-    audioPlayer.onProgress = function(a, b, c) {
-        console.log(a, b, c);
-        buffered = audioPlayer.audioElement.buffered;
+    audioPlayer.onVolumeChange = function(e) {
+        console.log('volume change', e);
+        audioPlayer.audioElement.volume = e.target.value;
+    }
+
+    audioPlayer.onControlsAttached = function(e) {
+        console.log('Controls attached', e);
+        $('.audio-spectrogram .audio-volume').val(
+                Math.round(audioPlayer.audioElement.volume, 2));
+    }
+
+    audioPlayer.onProgress = function(e) {
+        /**
+         * Handler for file download progress
+         */
+        console.log(e);
+
+        var buffered = audioPlayer.audioElement.buffered;
 
         ranges = new Array(); 
 
-        for (i = 0; i < buffered.length; i++) {
-            ranges[i] = new Array();
-            ranges[i][0] = buffered.start(i);
-            ranges[i][1] = buffered.end(i);
+        var indicators = $('.audio-spectrogram .buffered-indicators div');
+
+        for (var i = 0; i < buffered.length; i++) {
+            if (!(i in indicators)) {
+                $('<div style="display: none;"></div>')
+                    .appendTo($('.audio-spectrogram .buffered-indicators'))
+                    .fadeIn(500);
+                indicators = $('.audio-spectrogram .buffered-indicators div');
+            }
+            var posStart = ((buffered.start(i) / audioPlayer.audioElement.duration)
+                    * audioPlayer.imageElement.width());
+            var posStop = ((buffered.end(i) / audioPlayer.audioElement.duration)
+                    * audioPlayer.imageElement.width());
+            console.log('indicators', indicators);
+
+            var indicator = $(indicators[i]);
+
+            indicator.css('left', posStart);
+            indicator.css('width', posStop - posStart);
+        }
+
+        /*
+         * Clean up unused indicators
+         */
+        if (indicators.length > buffered.length) {
+            for (var i = buffered.length; i < indicators.length; i++) {
+                $(indicators[i]).fadeOut(500, function () {
+                    this.remove();
+                });
+            }
         }
-        console.log('ranges', ranges);
-        $('.audio-spectrogram .buffered').width(
-            (ranges[0][1] / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
     };
 
     audioPlayer.onSeek = function (e) {
+        /**
+         * Callback handler for seek event, which is a .click() event on the
+         * .seekbar element
+         */
         console.log('onSeek', e);
-        im = audioPlayer.imageElement;
-        pos = e.offsetX / im.width();
+
+        var im = audioPlayer.imageElement;
+        var pos = (e.offsetX || e.originalEvent.layerX) / im.width();
+
         audioPlayer.audioElement.currentTime = pos * audioPlayer.audioElement.duration;
         audioPlayer.audioElement.play();
         audioPlayer.setState(audioPlayer.PLAYING);
     };
 
+    audioPlayer.onEnded = function (e) {
+        audioPlayer.setState(audioPlayer.PAUSED);
+    }
+
     audioPlayer.playPause = function (e) {
         console.log('playPause', e);
         if (audioPlayer.audioElement.paused) {
@@ -81,13 +145,15 @@ var audioPlayer = new Object();
     audioPlayer.setState = function (state) {
         if (state == audioPlayer.state) {
             return;
+        } else {
+            audioPlayer.state = state;
         }
 
         switch (state) {
             case audioPlayer.PLAYING:
                 $('.audio-spectrogram .audio-control-play-pause')
                     .removeClass('paused').addClass('playing')
-                    .text('â\96 ');
+                    .text('â\96®â\96®');
                 break;
             case audioPlayer.PAUSED:
                 $('.audio-spectrogram .audio-control-play-pause')
@@ -98,37 +164,55 @@ var audioPlayer = new Object();
     };
 
     audioPlayer.durationChange = function () {
-        duration = audioPlayer.audioElement.duration;
+        // ???
     };
 
     audioPlayer.timeUpdate = function () {
-        currentTime = audioPlayer.audioElement.currentTime;
-        playhead = audioPlayer.imageElement.parent().find('.playhead');
-        playhead.css('width', (currentTime / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
-        time = formatTime(currentTime);
-        duration = formatTime(audioPlayer.audioElement.duration);
-        audioPlayer.imageElement.parent().find('.audio-currentTime').text(time + '/' + duration);
+        /**
+         * Callback handler for the timeupdate event, responsible for
+         * updating the playhead
+         */
+        var currentTime = audioPlayer.audioElement.currentTime;
+        var playhead = audioPlayer.imageElement.parent().find('.playhead');
+        playhead.css('width', (currentTime / audioPlayer.audioElement.duration)
+                * audioPlayer.imageElement.width());
+        var time = formatTime(currentTime);
+        var duration = formatTime(audioPlayer.audioElement.duration);
+        audioPlayer.imageElement.parent()
+            .find('.audio-currentTime')
+            .text(time + '/' + duration);
     };
 
     function formatTime(seconds) {
+        /**
+         * Format a time duration in (hh:)?mm:ss manner
+         */
         var h = Math.floor(seconds / (60 * 60));
         var m = Math.floor((seconds - h * 60 * 60) / 60);
         var s = Math.round(seconds - h * 60 * 60 - m * 60);
         return '' + (h ? (h < 10 ? '0' + h : h) + ':' : '') + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
     }
 
+    audioPlayer.formatTime = formatTime;
+
     audioPlayer.attachToImage = function (imageElement) {
         /**
          * Attach the player to an image element
          */
         console.log(imageElement);
-        im = $(imageElement);
+
+        var im = $(imageElement);
+
         audioPlayer.imageElement = im;
+
         $('<div class="playhead"></div>').appendTo(im.parent());
-        $('<div class="buffered"></div>').appendTo(im.parent());
+        $('<div class="buffered-indicators"></div>').appendTo(im.parent());
         $('<div class="seekbar"></div>').appendTo(im.parent());
         $('<div class="audio-control-play-pause paused">▶</div>').appendTo(im.parent());
         $('<div class="audio-currentTime">00:00</div>').appendTo(im.parent());
+        $('<input placeholder="Range input not supported" class="audio-volume"'
+                +'type="range" min="0" max="1" step="0.01" />').appendTo(im.parent());
+        $('.audio-spectrogram').trigger('attachedControls');
     };
 })(audioPlayer);
 
@@ -143,4 +227,3 @@ $(document).ready(function () {
     audioPlayer.init(audioElements[0]);
     audioPlayer.attachToImage($('.audio-spectrogram img')[0]);
 });
-