1/** 2 * @file MediaElement Playlist Feature (plugin). 3 * @author Andrew Berezovsky <[email protected]> 4 * Twitter handle: duozersk 5 * @author Original author: Junaid Qadir Baloch <[email protected]> 6 * Twitter handle: jeykeu 7 * Dual licensed under the MIT or GPL Version 2 licenses. 8 */ 9 10(function($) { 11 $.extend(mejs.MepDefaults, { 12 loopText: 'Repeat On/Off', 13 shuffleText: 'Shuffle On/Off', 14 nextText: 'Next Track', 15 prevText: 'Previous Track', 16 playlistText: 'Show/Hide Playlist' 17 }); 18 19 $.extend(MediaElementPlayer.prototype, { 20 // LOOP TOGGLE 21 buildloop: function(player, controls, layers, media) { 22 var t = this; 23 24 var loop = $('<div class="mejs-button mejs-loop-button ' + ((player.options.loop) ? 'mejs-loop-on' : 'mejs-loop-off') + '">' + 25 '<button type="button" aria-controls="' + player.id + '" title="' + player.options.loopText + '"></button>' + 26 '</div>') 27 // append it to the toolbar 28 .appendTo(controls) 29 // add a click toggle event 30 .click(function(e) { 31 player.options.loop = !player.options.loop; 32 $(media).trigger('mep-looptoggle', [player.options.loop]); 33 if (player.options.loop) { 34 loop.removeClass('mejs-loop-off').addClass('mejs-loop-on'); 35 //media.setAttribute('loop', 'loop'); 36 } 37 else { 38 loop.removeClass('mejs-loop-on').addClass('mejs-loop-off'); 39 //media.removeAttribute('loop'); 40 } 41 }); 42 43 t.loopToggle = t.controls.find('.mejs-loop-button'); 44 }, 45 loopToggleClick: function() { 46 var t = this; 47 t.loopToggle.trigger('click'); 48 }, 49 // SHUFFLE TOGGLE 50 buildshuffle: function(player, controls, layers, media) { 51 var t = this; 52 53 var shuffle = $('<div class="mejs-button mejs-shuffle-button ' + ((player.options.shuffle) ? 'mejs-shuffle-on' : 'mejs-shuffle-off') + '">' + 54 '<button type="button" aria-controls="' + player.id + '" title="' + player.options.shuffleText + '"></button>' + 55 '</div>') 56 // append it to the toolbar 57 .appendTo(controls) 58 // add a click toggle event 59 .click(function(e) { 60 player.options.shuffle = !player.options.shuffle; 61 $(media).trigger('mep-shuffletoggle', [player.options.shuffle]); 62 if (player.options.shuffle) { 63 shuffle.removeClass('mejs-shuffle-off').addClass('mejs-shuffle-on'); 64 } 65 else { 66 shuffle.removeClass('mejs-shuffle-on').addClass('mejs-shuffle-off'); 67 } 68 }); 69 70 t.shuffleToggle = t.controls.find('.mejs-shuffle-button'); 71 }, 72 shuffleToggleClick: function() { 73 var t = this; 74 t.shuffleToggle.trigger('click'); 75 }, 76 // PREVIOUS TRACK BUTTON 77 buildprevtrack: function(player, controls, layers, media) { 78 var t = this; 79 80 var prevTrack = $('<div class="mejs-button mejs-prevtrack-button mejs-prevtrack">' + 81 '<button type="button" aria-controls="' + player.id + '" title="' + player.options.prevText + '"></button>' + 82 '</div>') 83 .appendTo(controls) 84 .click(function(e){ 85 $(media).trigger('mep-playprevtrack'); 86 player.playPrevTrack(); 87 }); 88 89 t.prevTrack = t.controls.find('.mejs-prevtrack-button'); 90 }, 91 prevTrackClick: function() { 92 var t = this; 93 t.prevTrack.trigger('click'); 94 }, 95 // NEXT TRACK BUTTON 96 buildnexttrack: function(player, controls, layers, media) { 97 var t = this; 98 99 var nextTrack = $('<div class="mejs-button mejs-nexttrack-button mejs-nexttrack">' + 100 '<button type="button" aria-controls="' + player.id + '" title="' + player.options.nextText + '"></button>' + 101 '</div>') 102 .appendTo(controls) 103 .click(function(e){ 104 $(media).trigger('mep-playnexttrack'); 105 player.playNextTrack(); 106 }); 107 108 t.nextTrack = t.controls.find('.mejs-nexttrack-button'); 109 }, 110 nextTrackClick: function() { 111 var t = this; 112 t.nextTrack.trigger('click'); 113 }, 114 // PLAYLIST TOGGLE 115 buildplaylist: function(player, controls, layers, media) { 116 var t = this; 117 118 var playlistToggle = $('<div class="mejs-button mejs-playlist-button ' + ((player.options.playlist) ? 'mejs-hide-playlist' : 'mejs-show-playlist') + '">' + 119 '<button type="button" aria-controls="' + player.id + '" title="' + player.options.playlistText + '"></button>' + 120 '</div>') 121 .appendTo(controls) 122 .click(function(e) { 123 player.options.playlist = !player.options.playlist; 124 $(this).closest('.progression-playlist-height').toggleClass('active-progression'); 125 $(media).trigger('mep-playlisttoggle', [player.options.playlist]); 126 if (player.options.playlist) { 127 layers.children('.mejs-playlist').show(); 128 playlistToggle.removeClass('mejs-show-playlist').addClass('mejs-hide-playlist'); 129 } 130 else { 131 layers.children('.mejs-playlist').hide(); 132 playlistToggle.removeClass('mejs-hide-playlist').addClass('mejs-show-playlist'); 133 } 134 }); 135 136 t.playlistToggle = t.controls.find('.mejs-playlist-button'); 137 }, 138 playlistToggleClick: function() { 139 var t = this; 140 t.playlistToggle.trigger('click'); 141 }, 142 // PLAYLIST WINDOW 143 buildplaylistfeature: function(player, controls, layers, media) { 144 var playlist = $('<div class="mejs-playlist mejs-layer">' + 145 '<ul class="mejs"></ul>' + 146 '</div>') 147 .appendTo(layers); 148 if (!player.options.playlist) { 149 playlist.hide(); 150 } 151 if (player.options.playlistposition == 'bottom') { 152 playlist.css('top', player.options.audioHeight + 'px'); 153 } 154 else { 155 playlist.css('bottom', player.options.audioHeight + 'px'); 156 } 157 var getTrackName = function(trackUrl) { 158 var trackUrlParts = trackUrl.split("/"); 159 if (trackUrlParts.length > 0) { 160 return decodeURIComponent(trackUrlParts[trackUrlParts.length-1]); 161 } 162 else { 163 return ''; 164 } 165 }; 166 167 // calculate tracks and build playlist 168 var tracks = []; 169 //$(media).children('source').each(function(index, element) { // doesn't work in Opera 12.12 170 $('#'+player.id).find('.mejs-mediaelement source').each(function(index, element) { 171 if ($.trim(this.src) != '') { 172 var track = {}; 173 track.source = $.trim(this.src); 174 if ($.trim(this.title) != '') { 175 track.name = $.trim(this.title); 176 } 177 else { 178 track.name = getTrackName(track.source); 179 } 180 tracks.push(track); 181 } 182 }); 183 for (var track in tracks) { 184 layers.find('.mejs-playlist > ul').append('<li data-url="' + tracks[track].source + '" title="' + tracks[track].name + '">' + tracks[track].name + '</li>'); 185 } 186 187 // set the first track as current 188 layers.find('li:first').addClass('current played'); 189 // play track from playlist when clicking it 190 layers.find('.mejs-playlist > ul li').click(function(e) { 191 if (!$(this).hasClass('current')) { 192 $(this).addClass('played'); 193 player.playTrack($(this)); 194 } 195 else { 196 197 } 198 }); 199 200 // when current track ends - play the next one 201 media.addEventListener('ended', function(e) { 202 player.playNextTrack(); 203 }, false); 204 }, 205 playNextTrack: function() { 206 var t = this; 207 var tracks = t.layers.find('.mejs-playlist > ul > li'); 208 var current = tracks.filter('.current'); 209 var notplayed = tracks.not('.played'); 210 if (notplayed.length < 1) { 211 current.removeClass('played').siblings().removeClass('played'); 212 notplayed = tracks.not('.current'); 213 } 214 if (t.options.shuffle) { 215 var random = Math.floor(Math.random()*notplayed.length);
216 var nxt = notplayed.eq(random); 217 } 218 else { 219 var nxt = current.next(); 220 if (nxt.length < 1 && t.options.loop) { 221 nxt = current.siblings().first(); 222 } 223 } 224 if (nxt.length == 1) { 225 nxt.addClass('played'); 226 t.playTrack(nxt); 227 } 228 }, 229 playPrevTrack: function() { 230 var t = this; 231 var tracks = t.layers.find('.mejs-playlist > ul > li'); 232 var current = tracks.filter('.current'); 233 var played = tracks.filter('.played').not('.current'); 234 if (played.length < 1) { 235 current.removeClass('played'); 236 played = tracks.not('.current'); 237 } 238 if (t.options.shuffle) { 239 var random = Math.floor(Math.random()*played.length); 240 var prev = played.eq(random); 241 } 242 else { 243 var prev = current.prev(); 244 if (prev.length < 1 && t.options.loop) { 245 prev = current.siblings().last(); 246 } 247 } 248 if (prev.length == 1) { 249 current.removeClass('played'); 250 t.playTrack(prev); 251 } 252 }, 253 playTrack: function(track) { 254 var t = this; 255 t.pause(); 256 t.setSrc(track.attr('data-url')); 257 t.load(); 258 t.play(); 259 track.addClass('current').siblings().removeClass('current'); 260 }, 261 playTrackURL: function(url) { 262 var t = this; 263 var tracks = t.layers.find('.mejs-playlist > ul > li'); 264 var track = tracks.filter('[data-url="'+url+'"]'); 265 t.playTrack(track); 266 } 267 }); 268 269})(mejs.$);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.