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 $(media).trigger('mep-playlisttoggle', [player.options.playlist]); 125 if (player.options.playlist) { 126 layers.children('.mejs-playlist').show(); 127 playlistToggle.removeClass('mejs-show-playlist').addClass('mejs-hide-playlist'); 128 } 129 else { 130 layers.children('.mejs-playlist').hide(); 131 playlistToggle.removeClass('mejs-hide-playlist').addClass('mejs-show-playlist'); 132 } 133 }); 134 135 t.playlistToggle = t.controls.find('.mejs-playlist-button'); 136 }, 137 playlistToggleClick: function() { 138 var t = this; 139 t.playlistToggle.trigger('click'); 140 }, 141 // PLAYLIST WINDOW 142 buildplaylistfeature: function(player, controls, layers, media) { 143 var playlist = $('<div class="mejs-playlist mejs-layer">' + 144 '<ul class="mejs"></ul>' + 145 '</div>') 146 .appendTo(layers); 147 if (!player.options.playlist) { 148 playlist.hide(); 149 } 150 if (player.options.playlistposition == 'bottom') { 151 playlist.css('top', player.options.audioHeight + 'px'); 152 } 153 else { 154 playlist.css('bottom', player.options.audioHeight + 'px'); 155 } 156 var getTrackName = function(trackUrl) { 157 var trackUrlParts = trackUrl.split("/"); 158 if (trackUrlParts.length > 0) { 159 return decodeURIComponent(trackUrlParts[trackUrlParts.length-1]); 160 } 161 else { 162 return ''; 163 } 164 }; 165 166 // calculate tracks and build playlist 167 var tracks = []; 168 //$(media).children('source').each(function(index, element) { // doesn't work in Opera 12.12 169 $('#'+player.id).find('.mejs-mediaelement source').each(function(index, element) { 170 if ($.trim(this.src) != '') { 171 var track = {}; 172 track.source = $.trim(this.src); 173 if ($.trim(this.title) != '') { 174 track.name = $.trim(this.title); 175 } 176 else { 177 track.name = getTrackName(track.source); 178 } 179 tracks.push(track); 180 } 181 }); 182 for (var track in tracks) { 183 layers.find('.mejs-playlist > ul').append('<li data-url="' + tracks[track].source + '" title="' + tracks[track].name + '">' + tracks[track].name + '</li>'); 184 } 185 186 // set the first track as current 187 layers.find('li:first').addClass('current played'); 188 // play track from playlist when clicking it 189 layers.find('.mejs-playlist > ul li').click(function(e) { 190 if (!$(this).hasClass('current')) { 191 $(this).addClass('played'); 192 player.playTrack($(this)); 193 } 194 else { 195 player.play(); 196 } 197 }); 198 199 // when current track ends - play the next one 200 media.addEventListener('ended', function(e) { 201 player.playNextTrack(); 202 }, false); 203 }, 204 playNextTrack: function() { 205 var t = this; 206 var tracks = t.layers.find('.mejs-playlist > ul > li'); 207 var current = tracks.filter('.current'); 208 var notplayed = tracks.not('.played'); 209 if (notplayed.length < 1) { 210 current.removeClass('played').siblings().removeClass('played'); 211 notplayed = tracks.not('.current'); 212 } 213 if (t.options.shuffle) { 214 var random = Math.floor(Math.random()*notplayed.length);
215 var nxt = notplayed.eq(random); 216 } 217 else { 218 var nxt = current.next(); 219 if (nxt.length < 1 && t.options.loop) { 220 nxt = current.siblings().first(); 221 } 222 } 223 if (nxt.length == 1) { 224 nxt.addClass('played'); 225 t.playTrack(nxt); 226 } 227 }, 228 playPrevTrack: function() { 229 var t = this; 230 var tracks = t.layers.find('.mejs-playlist > ul > li'); 231 var current = tracks.filter('.current'); 232 var played = tracks.filter('.played').not('.current'); 233 if (played.length < 1) { 234 current.removeClass('played'); 235 played = tracks.not('.current'); 236 } 237 if (t.options.shuffle) { 238 var random = Math.floor(Math.random()*played.length); 239 var prev = played.eq(random); 240 } 241 else { 242 var prev = current.prev(); 243 if (prev.length < 1 && t.options.loop) { 244 prev = current.siblings().last(); 245 } 246 } 247 if (prev.length == 1) { 248 current.removeClass('played'); 249 t.playTrack(prev); 250 } 251 }, 252 playTrack: function(track) { 253 var t = this; 254 t.pause(); 255 t.setSrc(track.attr('data-url')); 256 t.load(); 257 t.play(); 258 track.addClass('current').siblings().removeClass('current'); 259 }, 260 playTrackURL: function(url) { 261 var t = this; 262 var tracks = t.layers.find('.mejs-playlist > ul > li'); 263 var track = tracks.filter('[data-url="'+url+'"]'); 264 t.playTrack(track); 265 } 266 }); 267 268})(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.