/**
* 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 += ' '+item.srces[i].src +'';
}
domItem += '';
return domItem;
},
createJDOMList = function(list){
if(!list.length){return $([]);}
//getItemProps,
var domList = '';
for(var i = 0, len = list.length; i < len; i++){
domList += createItemString(i, list[i]);
}
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);