3 $.widget( "panik.playlist", {
10 emission: "episode.slug",
11 episode: "episode.slug",
17 html5audioOptions:{controls:true,preload:true},
20 playlistContainer: $('<ol>'),
25 // Initialization logic here
27 this.debugContainer = $('<pre>').hide();
28 this.controlContainer = $('<div>');
29 this.playlistContainer = this.options.playlistContainer;
30 this.element.addClass(this.options.classes);
31 this.element.append(this.controlContainer);
32 this.element.append(this.playlistContainer);
33 this.element.append(this.debugContainer);
34 this.playlist = this.options.playlist;
35 this.buildPlaylistControls();
40 _setOption: function( key, value ) {
41 this.options[ key ] = value;
46 this.playlistContainer.find('audio').each(function(){
47 thePlaylist.playlist.push(thePlaylist.jsonifyAudio($(this)));
49 if(this.playlist.lenght >= 1){this.playlistContainer.show();}
51 this.debugContainer.text(
52 JSON.stringify(this.playlist, null, '\t')
56 savePlaylist: function(){
57 localStorage['playlist'] = JSON.stringify(this.playlist, null, '\t');
59 loadPlaylist: function(){
60 this.playlist = localStorage['playlist']?JSON.parse(localStorage['playlist']):this.playlist;
61 $.each(this.playlist,function(k,v){
62 thePlaylist.playlistContainer.append(thePlaylist._htmlifyJsonSound(v));
66 // Transform HTML5 <audio> to simple JSON object.
67 jsonifyAudio: function(audio) {
70 title: audio.attr('title'),
73 audio.children('source').each(function(){
74 sound.source[$(this).attr('type')] = $(this).attr('src');
78 // Transform JSON sound object to HTML container for playlist.
79 _htmlifyJsonSound: function(sound) {
80 var container = $('<li>');
81 var audio = $('<audio>',this.options.html5audioOptions).hide();
82 $.each(sound.source,function(k,v){
83 var source = $('<source>',{src:v,type:k});
86 audio.attr('title',sound.title)
87 .attr('data-origin',sound.id)
88 .on('play',function(){
89 $(this).addClass('playing');
90 container.addClass('active');
91 playpause.addClass('icon-pause').removeClass('icon-play');
92 thePlaylist.playlistContainer.find('audio:not(.playing)').trigger('stop');
93 thePlaylist.playpause.removeClass('icon-play').addClass('icon-pause');
94 thePlaylist.afterPlay();
95 }).on('pause',function(){
96 $(this).removeClass('playing');
97 playpause.addClass('icon-play').removeClass('icon-pause');
98 thePlaylist.playpause.removeClass('icon-pause').addClass('icon-play');
99 }).on('stop',function(){
100 $(this).trigger('pause');
101 $(this)[0].currentTime = 0;
102 container.removeClass('active');
103 }).on("ended", function(){
104 thePlaylist.playNext();
105 }).on('beforePause',function(){
107 }).on('beforePlay',function(){
108 thePlaylist.stopSounds();
111 var controls = $('<span>',{class:'soundControls controls'});
112 var html5 = $('<button>',{class:'icon-html5',click:function(){
115 var remove = $('<button>',{class:'icon-remove',click:function(){
117 thePlaylist._update();
119 var stop = $('<button>',{class:'icon-stop',click:function(){
120 audio.trigger('stop');
122 var playpause = $('<button>',{class:'icon-play',click:function(){
124 if (audio[0].paused == false) { audio.trigger('pause');
126 audio.trigger('beforePlay').trigger('play');
129 controls.append(playpause).append(stop).append(remove).append(html5);
130 var title = $('<span>',{class:"button title",html:sound.title,click:function(){
131 playpause.trigger('click');
134 container.append(controls).append(title).append(audio);
137 // Create a public method.
138 registerAudio: function(audio,success) {
139 var htmlAudio = this._htmlifyJsonSound(this.jsonifyAudio(audio));
140 this.playlistContainer.append(htmlAudio);
141 this.options.onAdd();
142 if(success){success();}
146 buildPlaylistControls: function() {
147 this.controls = $('<div>',{class:'playlistControls controls'});
148 this.toggleList = $('<button>',{class:"icon-list",click:function(){
149 thePlaylist.playlistContainer.toggle();
151 this.playpause = $('<button>',{class:"icon-play",click:function(){
152 thePlaylist.playPauseList();
154 this.stop = $('<button>',{class:"icon-stop",click:function(){
155 thePlaylist.stopSounds();
157 this.next = $('<button>',{class:"icon-step-forward",click:function(){
158 thePlaylist.playNext();
160 this.previous = $('<button>',{class:"icon-step-backward",click:function(){
161 thePlaylist.playPrevious();
163 this.controls.append(this.toggleList).append(this.previous).append(this.stop).append(this.playpause).append(this.next);
164 this.controlContainer.append(this.controls);
168 afterPlay: function() {
169 this.options.onPlay();
172 beforePlay: function() {
176 playPauseList: function() {
177 if(this.playpause.hasClass('icon-play')){
178 if(this.playlistContainer.find('.active')[0]){
179 this.playlistContainer.find('.active').find('audio').trigger('beforePlay').trigger('play');
181 this.playlistContainer.children('li').first().find('audio').trigger('beforePlay').trigger('play');
184 this.playlistContainer.find('.active').find('audio').trigger('pause');
189 playPrevious: function() {
190 this.playlistContainer.find('.active').prev().find('audio').trigger('beforePlay').trigger('play');
194 playNext: function() {
195 this.playlistContainer.find('.active').next().find('audio').trigger('beforePlay').trigger('play');
199 pauseSounds: function(selector) {
200 this.playlistContainer.find('audio').each(function(){$(this).trigger('pause');});
203 stopSounds: function(rewind) {
204 this.playlistContainer.find('audio').each(function(){
205 $(this).trigger('stop');