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.length >= 1){
50 this.playlistContainer.show();
53 this.playlistContainer.hide();
57 this.debugContainer.text(
58 JSON.stringify(this.playlist, null, '\t')
62 savePlaylist: function(){
63 localStorage['playlist'] = JSON.stringify(this.playlist, null, '\t');
65 loadPlaylist: function(){
66 this.playlist = localStorage['playlist']?JSON.parse(localStorage['playlist']):this.playlist;
67 $.each(this.playlist,function(k,v){
68 thePlaylist.playlistContainer.append(thePlaylist._htmlifyJsonSound(v));
72 // Transform HTML5 <audio> to simple JSON object.
73 jsonifyAudio: function(audio) {
76 title: audio.attr('title'),
79 audio.children('source').each(function(){
80 sound.source[$(this).attr('type')] = $(this).attr('src');
84 // Transform JSON sound object to HTML container for playlist.
85 _htmlifyJsonSound: function(sound) {
86 var container = $('<li>');
87 var audio = $('<audio>',this.options.html5audioOptions).hide();
88 $.each(sound.source,function(k,v){
89 var source = $('<source>',{src:v,type:k});
92 audio.attr('title',sound.title)
93 .attr('data-origin',sound.id)
94 .on('play',function(){
95 container.addClass('playing');
96 container.addClass('active');
97 playpause.addClass('icon-pause').removeClass('icon-play');
98 thePlaylist.playpause.removeClass('icon-play').addClass('icon-pause');
99 thePlaylist.afterPlay();
100 }).on('pause',function(){
101 $(this).removeClass('playing');
102 playpause.addClass('icon-play').removeClass('icon-pause');
103 thePlaylist.playpause.removeClass('icon-pause').addClass('icon-play');
104 }).on('stop',function(){
105 container.removeClass('active');
106 $(this).trigger('pause');
107 $(this)[0].currentTime = 0;
108 container.removeClass('active');
109 }).on("ended", function(){
110 thePlaylist.playNext();
111 }).on('beforePause',function(){
113 }).on('beforePlay',function(){
114 thePlaylist.playlistContainer.find('.active').removeClass('active');
115 thePlaylist.pauseSounds();
118 var controls = $('<span>',{class:'soundControls controls'});
119 var html5 = $('<button>',{class:'icon-html5',click:function(){
122 var remove = $('<button>',{class:'icon-remove',click:function(){
124 thePlaylist._update();
126 var stop = $('<button>',{class:'icon-stop',click:function(){
127 audio.trigger('stop');
129 var playpause = $('<button>',{class:'icon-play',click:function(){
131 if (audio[0].paused == false) { audio.trigger('pause');
133 audio.trigger('beforePlay').trigger('play');
136 controls.append(playpause).append(stop).append(remove).append(html5);
137 var title = $('<span>',{class:"button title",html:sound.title,click:function(){
138 playpause.trigger('click');
141 container.append(controls).append(title).append(audio);
144 // Create a public method.
145 registerAudio: function(audio,success) {
146 var htmlAudio = this._htmlifyJsonSound(this.jsonifyAudio(audio));
147 this.playlistContainer.append(htmlAudio);
148 this.options.onAdd();
149 if(success){success();}
153 buildPlaylistControls: function() {
154 this.controls = $('<div>',{class:'playlistControls controls'});
155 this.toggleList = $('<button>',{class:"icon-list",click:function(){
156 thePlaylist.playlistContainer.toggle();
158 this.playpause = $('<button>',{class:"icon-play",click:function(){
159 thePlaylist.playPauseList();
161 this.stop = $('<button>',{class:"icon-stop",click:function(){
162 thePlaylist.stopSounds();
164 this.next = $('<button>',{class:"icon-step-forward",click:function(){
165 thePlaylist.playNext();
167 this.previous = $('<button>',{class:"icon-step-backward",click:function(){
168 thePlaylist.playPrevious();
170 this.controls.append(this.toggleList).append(this.previous).append(this.stop).append(this.playpause).append(this.next);
171 this.controlContainer.append(this.controls);
175 afterPlay: function() {
176 this.options.onPlay();
179 beforePlay: function() {
183 playPauseList: function() {
184 if(this.playpause.hasClass('icon-play')){
185 if(this.playlistContainer.find('.active')[0]){
186 this.playlistContainer.find('.active').find('audio').trigger('beforePlay').trigger('play');
188 this.playlistContainer.children('li').first().find('audio').trigger('beforePlay').trigger('play');
191 this.playlistContainer.find('.active').find('audio').trigger('pause');
196 playPrevious: function() {
197 this.playlistContainer.find('.active').prev().find('audio').trigger('beforePlay').trigger('play');
201 playNext: function() {
202 this.playlistContainer.find('.active').next().find('audio').trigger('beforePlay').trigger('play');
206 pauseSounds: function(selector) {
207 this.playlistContainer.find('audio').each(function(){$(this).trigger('pause');});
210 stopSounds: function(rewind) {
211 this.playlistContainer.find('audio').each(function(){
212 $(this).trigger('stop');