/** * playlist plugin for the jMediaelement project | http://github.com/aFarkas/jMediaelement * @author Alexander Farkas * Copyright 2010, Alexander Farkas * Dual licensed under the MIT or GPL Version 2 licenses. * * Documentation: * http://protofunc.com/jme/plugins/playlist.html */ (function($){ //helpers for api var split = /\s*\|\s*|\s*\,\s*/g, itemSel = 'li[data-srces], li.play-item', getItemProps = function(item){ var props = { label: item.attr('data-label'), srces: [] }, poster = item.attr('data-poster'), srces = $('a', item), nameElem ; if(poster){ props.poster = $.multimediaSupport.makeAbsURI(poster); } else { poster = $('img', item)[0]; if(poster){ props.poster = poster.src; } } if(!props.label){ nameElem = $('.item-name', item); props.label = $.trim( ( ( nameElem[0] ) ? nameElem : item ).text() ); } if( srces.length ){ $.each(srces, function(i, src){ props.srces[i] = {src: this.href}; var type = $.attr(src, 'type'); if( type ){ props.srces[i].type = type; } }); } else { props.srces = (item.attr('data-srces') || '').split(split); } return props; }, getPlayList = function( elem ){ var data = $.data(elem, 'mediaElemSupport'); if( !data.playlist ){ data.playlist = $([]); } return data; }, loadPrevNext = function(api, list, dir, autoplay){ var items = $(itemSel, list), index = items.index( items.filter('.ui-state-active') ) + dir ; if( index >= items.length || index < 0 ){ if( !list.hasClass('loop') ){return;} if( index >= items.length ){ index = 0; } else { index = items.length - 1; } } if ( items[index] ) { list.loadPlaylistItem(items[index], items, autoplay); } }, createItemString = function(_i, item){ if( !$.isArray(item.srces) ){ item.srces = [item.srces]; } if( typeof item === 'string' ){ item = {src: item}; } var domItem = '
  • '+item.name+''; } for(var i = 0, len = item.srces.length; i < len; i++){ if(typeof item.srces[i] === 'string'){ item.srces[i] = {src: item.srces[i]}; } domItem += ' '; } domItem += '
  • '; return domItem; }, createJDOMList = function(list){ if(!list.length){return $([]);} //getItemProps, var domList = ''; return $(domList); } ; $.each(['activatePlaylist', 'loadPlaylistItem', 'loadNextPlaylistItem', 'loadPreviousPlaylistItem'], function(i, name){ var _name = '_'+ name; $.fn[name] = function(){ var args = Array.prototype.slice.call(arguments, 0); return this.each(function(){ var jme = $.data(this, 'playlistFor'), api ; if( jme ){ args.unshift(this); api = jme.getJMEAPI(); if( name !== 'activatePlaylist' ){ api._activatePlaylist.call(api, this); } } else { api = getPlayList(this); args.unshift(api.playlist); api = api.apis[api.name]; } if( api ){ api[_name].apply(api, args); } }); }; }); $.multimediaSupport.fn._extend({ _activatePlaylist: function(list){ list = $(list); var data = getPlayList(this.element); if( data.playlist[0] === list[0] || list.hasClass('active-playlist') ){return;} var oldList = data.playlist.removeClass('active-playlist'); $(itemSel, data.playlist).removeClass('ui-state-active'); if(!list[0]){ list = data.playlist; } data.playlist = list; list.addClass('active-playlist'); // if we have no source, load and play ui-state-active marked or first playlist-item var items = $(itemSel, list), activeItem = items.filter('.ui-state-active') ; if( !activeItem[0] ){ activeItem = items; } this._loadPlaylistItem(list, activeItem[0], items); this._trigger({ type: 'playlistchange', playlist: list, oldPlaylist: oldList }); }, _loadPlaylistItem: function(list, item, _items, _autoplay){ if(!_items){ _items = $(itemSel, list); } _items = $(_items); item = $(item); var oldItem = _items .filter('.ui-state-active') .removeClass('ui-state-active'), itemProps = getItemProps(item), curIndex = _items.index( item ), elem = $(this.element), available = {next: true, prev: true} ; item.addClass('ui-state-active'); this.loadSrc(itemProps.srces, itemProps.poster, itemProps.label ); this._trigger({ type: 'playlistitemchange', list: list, items: _items, props: itemProps, currentIndex: curIndex, currentItem: item, previousItem: oldItem, autoplay: _autoplay }); if( _autoplay ){ setTimeout(function(){ elem.play(); }, 0); } }, _loadNextPlaylistItem: function(list, autoplay){ loadPrevNext(this, list, 1, autoplay); }, _loadPreviousPlaylistItem: function(list, autoplay){ loadPrevNext(this, list, -1, autoplay); } }); $.multimediaSupport.fn._extend({ playlist: function(list, _addThemeRoller, activate){ var elem = $(this.element); if( !list ){ return getPlayList(this.element).playlist; } if( $.isArray(list) ){ list = createJDOMList( list ); } else { list = $( list ); } if(activate || !$.attr(this.element, 'srces').length ){ this._activatePlaylist(list); } if( !list.data('playlistFor') ) { var items = $(itemSel, list); elem .bind('ended.playlist', function(){ var autoplay = list.hasClass('autoplay-next'); if( list.hasClass('active-playlist') && ( autoplay || list.hasClass('autoload-next') ) ){ //opera is not responding // ToDo: should delay ended event instead setTimeout(function(){ elem.loadNextPlaylistItem(list, autoplay); }, 9); } }) ; list .delegate(itemSel, 'ariaclick', function(e){ list.loadPlaylistItem(this, undefined, true); e.preventDefault(); }) ; if(_addThemeRoller){ list.addClass('ui-corner-all ui-widget-header'); items.addClass('ui-state-default ui-widget-content ui-corner-all'); } if( !items.attr('role') ){ items .attr({ role: 'button', tabindex: '0' }) .find('a') .attr({ role: 'presentation', tabindex: '-1' }) ; } list.data('playlistFor', elem); this._trigger({ type: 'playlistcreated', playlist: list }); } return list; } }, true); $.fn.jmeControl.addControl('playlist', function(playlist, element, api, o){ element.playlist( playlist, o.addThemeRoller, o.playlist.activate ); }); })(jQuery);