]> git.0d.be Git - panikweb-esperanzah.git/blob - espeweb/static/js/audioPlayer.js
mutate into an addon module for panikweb
[panikweb-esperanzah.git] / espeweb / static / js / audioPlayer.js
1 (function($) {
2         var thePlaylist;
3         $.widget( "panik.playlist", {
4                 /*
5                         sound = {
6                                 source :{
7                                         ogg:"oggURL",
8                                         mp3:"mp3URL"
9                                 },
10                                 emission: "episode.slug",
11                                 episode: "episode.slug",
12                                 id:""
13                         }
14                 */
15                 options: {
16                         playlist: [],
17                         html5audioOptions:{controls:true,preload:"none"},
18                         classes: "",
19                         itemClasses: "",
20                         controlContainer: $('<div>'),
21                         playlistContainer: $('<ol>'),
22                         onLoad: function(){},
23                         onAdd: function(){},
24                         onPlay: function(){},
25                         onUpdate: function(){},
26                         onEnded: function(){},
27                 },
28                 _create: function() {
29                 // Initialization logic here
30                         thePlaylist = this;     
31                         this.isActive = false;
32                         this.isLastAdd = false;
33                         this.controlButtons = []
34                         this.debugContainer = $('<pre>').hide();
35                         this.controlContainer = this.options.controlContainer;
36                         this.playlistContainer = this.options.playlistContainer;
37                         this.element.addClass(this.options.classes);    
38                         this.element.append(this.controlContainer);     
39                         this.element.append(this.playlistContainer);
40                         this.element.append(this.debugContainer);
41                         this.playlist = this.options.playlist;
42                         this.buildPlaylistControls();
43                         this.loadPlaylist();
44                         this._update();
45                         this.options.onLoad(this);
46                 },
47
48                 _setOption: function( key, value ) {
49                         this.options[ key ] = value;
50                         this._update();
51                 },
52                 _update: function() {   
53                         this.playlist = [];     
54                         this.playlistContainer.find('audio').each(function(){
55                                 thePlaylist.playlist.push(thePlaylist.jsonifyAudio($(this)));
56                         });
57                         this.debugContainer.text(
58                                 JSON.stringify(this.playlist, null, '\t')
59                         );
60                         this.savePlaylist();
61                         this.options.onUpdate(this);
62                         return this.playlist;
63                 },
64                 _reset: function() {    
65                         this.isActive =false;
66                         this.stopSounds();
67                         this.playlistContainer.find('*').remove();
68                         this._update();
69                 },
70                 savePlaylist: function(){
71                         var JSONPlaylist = JSON.stringify(this.playlist, null, '\t');
72                         if (localStorage !== null && localStorage !== undefined) {
73                                 localStorage['playlist'] = JSON.stringify(this.playlist, null, '\t');
74                         }
75                 },
76                 loadPlaylist: function(){
77                         if (localStorage !== null && localStorage !== undefined) {
78                                 this.playlist = localStorage['playlist']?JSON.parse(localStorage['playlist']):this.playlist;
79                         }
80                         $.each(this.playlist,function(k,v){
81                                 thePlaylist.playlistContainer.append(thePlaylist._htmlifyJsonSound(v));
82                         });
83                         return this.playlist;
84                 },
85                 // Transform HTML5 <audio> to simple JSON object.
86                 jsonifyAudio: function(audio) {
87                         var sound = {
88                                 source :{},
89                                 title: audio.attr('title'),
90                                 id:audio.attr('id'),
91                                 sound_id:audio.data('sound-id'),
92                                 url:audio.attr('data-url'),
93                                 focus:audio.attr('data-player-focus')
94                         };
95                         audio.children('source').each(function(){
96                                 sound.source[$(this).attr('type')] = $(this).attr('src');
97                         });
98                         return sound;
99                 },
100                 // Play next sound
101                 setFocus: function(element) {
102                         this.isActive = element;
103                         this.playlistContainer.find('li').each(function(){
104                                 $(this).removeClass('active');
105                                 $(this).find('audio').removeAttr('data-player-focus');
106                         });
107                         this.isActive.addClass('active').find('audio').attr('data-player-focus',true);
108                         this._update();
109                 },
110                 // Transform JSON sound object to HTML container for playlist.
111                 _htmlifyJsonSound: function(sound) {
112                         var container = $('<li>').attr('data-origin',sound.id);
113                         var audio = $('<audio>',this.options.html5audioOptions)
114                                 .attr('title',sound.title).hide()
115                                 .attr('data-sound-id', sound.sound_id)
116                                 .attr('data-url',sound.url);
117                         var audio_str = sound.sound_id + ': ' + sound.title;
118                         $.each(sound.source,function(k,v){
119                                 var source = $('<source>',{src:v,type:k});
120                                 audio.append(source);
121                         });
122                         audio.on('play',function(e){
123                                 if (e.originalEvent === undefined) {
124                                         return;
125                                 }
126                                 if (typeof (_paq) == 'object') {
127                                         _paq.push(['trackEvent', 'Audio', 'Play', audio_str]);
128                                 }
129                                 thePlaylist.setFocus(container);
130                                 container.addClass('playing');
131                                 playpause.addClass('action-pause').removeClass('action-play');
132                                 thePlaylist.controlButtons['playpause'].removeClass('action-play').addClass('action-pause');
133                                 thePlaylist.afterPlay();
134                                 var sound_id = $(e.target).data('sound-id');
135                                 $(document).trigger('panik:play', {'sound_id': sound_id});
136                         }).on('pause',function(e){
137                                 $(this).removeClass('playing');
138                                 playpause.addClass('action-play').removeClass('action-pause');
139                                 var sound_id = $(e.target).data('sound-id');
140                                 $(document).trigger('panik:pause', {'sound_id': sound_id});
141                                 thePlaylist.controlButtons['playpause'].removeClass('action-pause').addClass('action-play');
142                         }).on('stop',function(event){
143                                 $(this).trigger('pause');
144                                 if($(this)[0].currentTime){$(this)[0].currentTime = 0;}
145                         }).on("ended", function(e){
146                                 if (typeof (_paq) == 'object') {
147                                         _paq.push(['trackEvent', 'Audio', 'End', audio_str]);
148                                 }
149                                 thePlaylist.ended();
150                         }).on('beforePause',function(){
151                                 return this;
152                         }).on('beforePlay',function(){
153                                 thePlaylist.pauseSounds();
154                                 return this;
155                         }).on('timeupdate', function(event) {
156                                 var position = 1.0 * event.target.currentTime / event.target.duration;
157                                 var sound_id = $(event.target).data('sound-id');
158                                 $(document).trigger('panik:timeupdate',
159                                                 {'sound_id': sound_id, 'position': position});
160                         });
161                         var controls = $('<span>',{'class':'soundControls controls'});
162                         var link = $('<a>',{href:sound.url,'class':'button icon-external-link'});
163                         var remove = $('<button>',{title:"Stop",'class':'no-icon-remove',click:function(){
164                                 container.remove();
165                                 thePlaylist._update();
166                         }});
167                         var stop = $('<button>',{title:"Stop",'class':'icon-stop',click:function(){
168                                 audio.trigger('stop');
169                         }}).hide();
170                         var playpause = $('<button>',{title:"Play/Pause",'class':'action-play',click:function(){
171                                 
172                                   if (audio[0].paused == false) { audio.trigger('pause');
173                                   } else {
174                                         audio.trigger('beforePlay').trigger('play');
175                                 }
176                         }});
177                         controls.append(playpause).append(stop).append(remove);
178                         var title = $('<a>',{title:"More information",href:sound.url,'class':"button title",html:sound.title});
179                         container.append(controls).append(title).append(audio);
180                         if(sound.focus){thePlaylist.setFocus(container);}
181                         return container;
182                 },
183                 // Create a public method.
184                 registerAudio: function(audio,success) {
185                         var sound_id = audio.data('sound-id');
186                         if (this.playlistContainer.find('[data-sound-id=' + sound_id + ']').length) {
187                                 /* already in playlist */
188                                 return;
189                         }
190                         var audioObj = this.jsonifyAudio(audio);
191                         var htmlAudio = this._htmlifyJsonSound(audioObj);
192                         this.playlistContainer.append(htmlAudio);
193                         this.isLastAdd = htmlAudio;
194                         if(!this.isActive){this.setFocus(this.isLastAdd);}
195                         this.options.onAdd(this);
196                         if(success){success();}
197                         this._update();
198                 },
199                 // Play next sound
200                 bindControl: function(control,audio,element,options) {
201                         element.addClass('loading');
202                         audioID = audio.attr('id');                     
203                         //TODO for controls in page content
204                 },
205                 // Play next sound
206                 registerControl: function(name,options) {
207                         this.controlButtons[name] = $('<button>',options);
208                         this.controlContainer.append(this.controlButtons[name]);
209                 },
210                 // Build controls
211                 buildPlaylistControls: function() {
212                         this.controlContainer.empty();
213                         /*
214                         this.registerControl('toggleList',{class:"icon-list",click:     function(){ 
215                                 thePlaylist.playlistContainer.toggle();
216                         }});
217                         this.registerControl('clearList',{class:"icon-trash",click:     function(){ 
218                                 thePlaylist.playlistContainer.empty();
219                                 thePlaylist._update();
220                         }});
221                         */
222                         this.registerControl('playpause',{'class':"action-play playPause",click:        function(){
223                                 thePlaylist.playPauseList();
224                         }});
225                         return true;
226                 },
227                 // Play next sound
228                 afterPlay: function() {
229                         console.log('after play');
230                         this.options.onPlay(this);
231                 },
232                 // Play next sound
233                 beforePlay: function() {
234                         console.log('before play');
235                         this.stopSounds();
236                 },
237                 // Play next sound
238                 getActive: function() {
239                         if(!this.isActive){
240                                 this.isActive = this.playlistContainer.children('li').first();                          
241                         }
242                         return this.isActive;
243                 },
244                 playSoundId: function(sound_id) {
245                         this.playlistContainer.find('audio[data-sound-id="' + sound_id + '"]'
246                                         ).trigger('beforePlay').trigger('play');
247                 },
248                 // Play next sound
249                 playPauseList: function() {
250                         if(this.controlButtons['playpause'].hasClass('action-play')){
251                                 this.getActive().find('audio').trigger('beforePlay').trigger('play');
252                         }else{
253                                 this.getActive().find('audio').trigger('pause');        
254                         }
255                         return true;
256                 },
257                 // Play next sound
258                 playPrevious: function() {
259                         this.getActive().prev().find('audio').trigger('beforePlay').trigger('play');
260                         return true;
261                 },
262                 // Play next sound
263                 playNext: function() {
264                         this.getActive().next().find('audio').trigger('beforePlay').trigger('play');
265                         return true;
266                 },
267                 // Play next sound
268                 playFirst: function() {
269                         this.playlistContainer.find('audio').first().trigger('beforePlay').trigger('play');
270                         return true;
271                 },
272                 // Play next sound
273                 playLast: function() {
274                         this.playlistContainer.find('audio').last().trigger('beforePlay').trigger('play');
275                         return true;
276                 },
277                 // Pause all sounds.
278                 pauseSounds: function() {
279                         this.playlistContainer.find('audio').each(function(){$(this).trigger('pause');});       
280                 },
281                 ended: function() {
282                         this.options.onEnded(this);
283                 },
284                 // stop all sounds.
285                 stopSounds: function() {
286                         this.playlistContainer.find('audio').each(function(){$(this).trigger('stop');});        
287                 },
288                 reset: function() {
289                         this.isActive = false;
290                         this.stopSounds();
291                         this.playlistContainer.find('*').remove();
292                         this._update();
293                 }
294         });
295 })(jQuery);
296