-(function($) {
- /*
- sound = {
- ogg:"oggURL",
- mp3:"mp3URL",
- emission: "episode.slug",
- episode: "episode.slug",
- id:""
- }
- */
+(function($) {
+ var thePlaylist;
$.widget( "panik.playlist", {
+ /*
+ sound = {
+ source :{
+ ogg:"oggURL",
+ mp3:"mp3URL"
+ },
+ emission: "episode.slug",
+ episode: "episode.slug",
+ id:""
+ }
+ */
options: {
playlist: [],
- html5audioOptions:{class:"hidden", controls:false,preload:true},
- classes: "small",
+ html5audioOptions:{controls:true,preload:"none"},
+ classes: "",
+ itemClasses: "",
+ controlContainer: $('<div>'),
playlistContainer: $('<ol>'),
- debugContainer: $('<div>').hide(),
+ onLoad: function(){},
+ onAdd: function(){},
+ onPlay: function(){},
+ onUpdate: function(){},
},
_create: function() {
- // Initialization logic here
- var self = this;
- this.element.addClass(this.options.classes);
- this.element.append(this.options.audioContainer);
- this.element.append(this.options.playlistContainer);
- this.element.append(this.options.debugContainer);
- var previousPlaylist = localStorage['playlist']?JSON.parse(localStorage['playlist']):[];
- this.playlist = $.extend([], previousPlaylist);
+ // Initialization logic here
+ thePlaylist = this;
+ this.isActive = false;
+ this.isLastAdd = false;
+ this.controlButtons = []
+ this.debugContainer = $('<pre>').hide();
+ this.controlContainer = this.options.controlContainer;
+ this.playlistContainer = this.options.playlistContainer;
+ this.element.addClass(this.options.classes);
+ this.element.append(this.controlContainer);
+ this.element.append(this.playlistContainer);
+ this.element.append(this.debugContainer);
+ this.playlist = this.options.playlist;
+ this.buildPlaylistControls();
+ this.loadPlaylist();
this._update();
+ this.options.onLoad(this);
},
_setOption: function( key, value ) {
this.options[ key ] = value;
this._update();
},
- _update: function() {
- localStorage['playlist'] = JSON.stringify(this.playlist);
- this.options.debugContainer.text(
- JSON.stringify(this.playlist)
+ _update: function() {
+ this.playlist = [];
+ this.playlistContainer.find('audio').each(function(){
+ thePlaylist.playlist.push(thePlaylist.jsonifyAudio($(this)));
+ });
+ this.debugContainer.text(
+ JSON.stringify(this.playlist, null, '\t')
);
- this._buildhtmlPlaylist();
+ this.savePlaylist();
+ this.options.onUpdate(this);
+ return this.playlist;
},
- // Create a public method.
- registerSound: function(sound) {
- this.playlist.push(sound);
+ _reset: function() {
+ this.isActive =false;
+ this.stopSounds();
+ this.playlistContainer.find('*').remove();
this._update();
},
- // Create a public method.
- removeSound: function(k) {
- this.playlist.splice(k, 1);
- this._update();
+ savePlaylist: function(){
+ var JSONPlaylist = JSON.stringify(this.playlist, null, '\t');
+ if (localStorage !== null && localStorage !== undefined) {
+ localStorage['playlist'] = JSON.stringify(this.playlist, null, '\t');
+ }
},
- // Create a public method.
- pauseSounds: function() {
- this.options.playlistContainer.find('audio').each(function(){$(this)[0].pause();});
+ loadPlaylist: function(){
+ if (localStorage !== null && localStorage !== undefined) {
+ this.playlist = localStorage['playlist']?JSON.parse(localStorage['playlist']):this.playlist;
+ }
+ $.each(this.playlist,function(k,v){
+ thePlaylist.playlistContainer.append(thePlaylist._htmlifyJsonSound(v));
+ });
+ return this.playlist;
},
- // Create a public method.
- _buildhtmlSound: function(sound,k) {
- var self = this;
- var container = $('<div>');
- var audio = $('<audio>',this.options.html5audioOptions);
+ // Transform HTML5 <audio> to simple JSON object.
+ jsonifyAudio: function(audio) {
+ var sound = {
+ source :{},
+ title: audio.attr('title'),
+ sound_id:audio.data('sound-id'),
+ url:audio.attr('data-url'),
+ focus:audio.attr('data-player-focus')
+ };
+ audio.children('source').each(function(){
+ sound.source[$(this).attr('type')] = $(this).attr('src');
+ });
+ return sound;
+ },
+ // Play next sound
+ setFocus: function(element) {
+ this.isActive = element;
+ this.playlistContainer.find('li').each(function(){
+ $(this).removeClass('active');
+ $(this).find('audio').removeAttr('data-player-focus');
+ });
+ this.isActive.addClass('active').find('audio').attr('data-player-focus',true);
+ this._update();
+ },
+ // Transform JSON sound object to HTML container for playlist.
+ _htmlifyJsonSound: function(sound) {
+ var container = $('<li>');
+ var audio = $('<audio>',this.options.html5audioOptions)
+ .attr('title',sound.title).hide()
+ .attr('data-sound-id', sound.sound_id)
+ .attr('data-url',sound.url);
+ var audio_str = sound.sound_id + ': ' + sound.title;
$.each(sound.source,function(k,v){
var source = $('<source>',{src:v,type:k});
audio.append(source);
});
- var title = $('<button>',{html:sound.title,click:function(){
- if (audio[0].paused == false) {
- audio[0].pause();
- $(this).removeClass('active');
+ audio.on('play',function(e){
+ if (e.originalEvent === undefined) {
+ return;
+ }
+ if (typeof (_paq) == 'object') {
+ _paq.push(['trackEvent', 'Audio', 'Play', audio_str]);
+ }
+ thePlaylist.setFocus(container);
+ container.addClass('playing');
+ playpause.addClass('icon-pause').removeClass('icon-play');
+ thePlaylist.controlButtons['playpause'].removeClass('icon-play').addClass('icon-pause');
+ thePlaylist.afterPlay();
+ var sound_id = $(e.target).data('sound-id');
+ $(document).trigger('panik:play', {'sound_id': sound_id});
+ }).on('pause',function(e){
+ $(this).removeClass('playing');
+ playpause.addClass('icon-play').removeClass('icon-pause');
+ var sound_id = $(e.target).data('sound-id');
+ $(document).trigger('panik:pause', {'sound_id': sound_id});
+ thePlaylist.controlButtons['playpause'].removeClass('icon-pause').addClass('icon-play');
+ }).on('stop',function(event){
+ $(this).trigger('pause');
+ if($(this)[0].currentTime){$(this)[0].currentTime = 0;}
+ }).on("ended", function(e){
+ if (typeof (_paq) == 'object') {
+ _paq.push(['trackEvent', 'Audio', 'End', audio_str]);
+ }
+ thePlaylist.playNext();
+ }).on('beforePause',function(){
+ return this;
+ }).on('beforePlay',function(){
+ thePlaylist.pauseSounds();
+ return this;
+ }).on('timeupdate', function(event) {
+ var position = 1.0 * event.target.currentTime / event.target.duration;
+ var sound_id = $(event.target).data('sound-id');
+ $(document).trigger('panik:timeupdate',
+ {'sound_id': sound_id, 'position': position});
+ });
+ var controls = $('<span>',{'class':'soundControls controls'});
+ var link = $('<a>',{href:sound.url,'class':'button icon-external-link'});
+ var remove = $('<button>',{title:"Remove from list",'class':'icon-remove',click:function(){
+ audio.trigger('stop');
+ container.remove();
+ thePlaylist._update();
+ }});
+ var stop = $('<button>',{title:"Stop",'class':'icon-stop',click:function(){
+ audio.trigger('stop');
+ }}).hide();
+ var playpause = $('<button>',{title:"Play/Pause",'class':'icon-play',click:function(){
+
+ if (audio[0].paused == false) { audio.trigger('pause');
} else {
- self.options.playlistContainer.find('.active').removeClass('active');
- $(this).addClass('active');
- self.pauseSounds();
- audio[0].play();
- }
+ audio.trigger('beforePlay').trigger('play');
+ }
+ }});
+ controls.append(playpause).append(stop).append(remove);
+ var title = $('<a>',{title:"More information",href:sound.url,'class':"button title",html:sound.title});
+ container.append(controls).append(title).append(audio);
+ if(sound.focus){thePlaylist.setFocus(container);}
+ return container;
+ },
+ // Create a public method.
+ registerAudio: function(audio,success) {
+ var sound_id = audio.data('sound-id');
+ if (this.playlistContainer.find('[data-sound-id=' + sound_id + ']').length) {
+ /* already in playlist */
+ return;
+ }
+ var audioObj = this.jsonifyAudio(audio);
+ var htmlAudio = this._htmlifyJsonSound(audioObj);
+ this.playlistContainer.append(htmlAudio);
+ this.isLastAdd = htmlAudio;
+ if(!this.isActive){this.setFocus(this.isLastAdd);}
+ this.options.onAdd(this);
+ if(success){success();}
+ this._update();
+ },
+ // Play next sound
+ bindControl: function(control,audio,element,options) {
+ element.addClass('loading');
+ audioID = audio.data('souce-id');
+ //TODO for controls in page content
+ },
+ // Play next sound
+ registerControl: function(name,options) {
+ this.controlButtons[name] = $('<button>',options);
+ this.controlContainer.append(this.controlButtons[name]);
+ },
+ // Build controls
+ buildPlaylistControls: function() {
+ this.controlContainer.empty();
+ /*
+ this.registerControl('toggleList',{class:"icon-list",click: function(){
+ thePlaylist.playlistContainer.toggle();
+ }});
+ this.registerControl('clearList',{class:"icon-trash",click: function(){
+ thePlaylist.playlistContainer.empty();
+ thePlaylist._update();
+ }});
+ */
+ this.registerControl('previous',{'class':"icon-step-backward",click:function(){
+ thePlaylist.playPrevious();
}});
- var remover = $('<button>',{class:'icon-remove',click:function(){
- self.removeSound(k);
+ this.registerControl('stop',{'class':"icon-stop",click: function(){
+ thePlaylist.stopSounds();
}});
- return container.append(remover).append(title).append(audio);
+ this.registerControl('playpause',{'class':"icon-play playPause",click: function(){
+ thePlaylist.playPauseList();
+ }});
+ this.registerControl('next',{'class':"icon-step-forward",click: function(){
+ thePlaylist.playNext();
+ }});
+ return true;
},
- // Create a private method.
- _buildhtmlPlaylist: function( argument ) {
- var self = this;
- self.options.playlistContainer.empty();
- $.each(this.playlist,function(k,v){
- var soundHtml = self._buildhtmlSound(v,k);
- var listItem = $('<li>',{html:soundHtml});
- self.options.playlistContainer.append(listItem);
- });
+ // Play next sound
+ afterPlay: function() {
+ this.options.onPlay(this);
},
- // Create a public method.
- showAlert: function( argument ) {
- // ...
- alert('me');
+ // Play next sound
+ beforePlay: function() {
+ this.stopSounds();
+ },
+ // Play next sound
+ getActive: function() {
+ if(!this.isActive){
+ this.isActive = this.playlistContainer.children('li').first();
+ }
+ return this.isActive;
+ },
+ playSoundId: function(sound_id) {
+ this.playlistContainer.find('audio[data-sound-id="' + sound_id + '"]'
+ ).trigger('beforePlay').trigger('play');
+ },
+ // Play next sound
+ playPauseList: function() {
+ if(this.controlButtons['playpause'].hasClass('icon-play')){
+ this.getActive().find('audio').trigger('beforePlay').trigger('play');
+ }else{
+ this.getActive().find('audio').trigger('pause');
+ }
+ return true;
+ },
+ // Play next sound
+ playPrevious: function() {
+ this.getActive().prev().find('audio').trigger('beforePlay').trigger('play');
+ return true;
+ },
+ // Play next sound
+ playNext: function() {
+ this.getActive().next().find('audio').trigger('beforePlay').trigger('play');
+ return true;
+ },
+ // Play next sound
+ playFirst: function() {
+ this.playlistContainer.find('audio').first().trigger('beforePlay').trigger('play');
+ return true;
+ },
+ // Play next sound
+ playLast: function() {
+ this.playlistContainer.find('audio').last().trigger('beforePlay').trigger('play');
+ return true;
+ },
+ // Pause all sounds.
+ pauseSounds: function() {
+ this.playlistContainer.find('audio').each(function(){$(this).trigger('pause');});
+ },
+ // stop all sounds.
+ stopSounds: function() {
+ this.playlistContainer.find('audio').each(function(){$(this).trigger('stop');});
},
});
})(jQuery);