CC-3395: Play preview for playlists and timelines for shows should show a list under the pop-up player which will play the entire playlist.
- Updated jplayer so it now shows a list view under the player which shows details of the track being played, and for playlists the entire playlist list. - Also enabled playing playlists from the library.
This commit is contained in:
parent
709e117f41
commit
470cf0dbf8
|
@ -148,7 +148,7 @@ class ApiController extends Zend_Controller_Action
|
|||
header('Content-Disposition: inline; filename="'.$file_base_name.'"');
|
||||
}
|
||||
|
||||
$this->smartReadFile($filepath, $ext);
|
||||
$this->smartReadFile($filepath, 'audio/'.$ext);
|
||||
exit;
|
||||
}else{
|
||||
header ("HTTP/1.1 404 Not Found");
|
||||
|
@ -170,7 +170,7 @@ class ApiController extends Zend_Controller_Action
|
|||
* @link https://groups.google.com/d/msg/jplayer/nSM2UmnSKKA/Hu76jDZS4xcJ
|
||||
* @link http://php.net/manual/en/function.readfile.php#86244
|
||||
*/
|
||||
function smartReadFile($location, $mimeType = 'audio/mpeg')
|
||||
function smartReadFile($location, $mimeType = 'audio/mp3')
|
||||
{
|
||||
$size= filesize($location);
|
||||
$time= date('r', filemtime($location));
|
||||
|
|
|
@ -58,7 +58,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/main_library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/css/media_library.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
@ -88,8 +88,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
if (isset($this->pl_sess->id) && $screen == "playlist") {
|
||||
$menu["pl_add"] = array("name"=> "Add to Playlist", "icon" => "copy");
|
||||
}
|
||||
//Open a jPlayer window and play the audio clip.
|
||||
$menu["play"] = array("name"=> "Play", "icon" => "big_play");
|
||||
|
||||
|
||||
$menu["edit"] = array("name"=> "Edit Metadata", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}");
|
||||
|
||||
|
@ -134,6 +133,9 @@ class LibraryController extends Zend_Controller_Action
|
|||
$menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete");
|
||||
}
|
||||
|
||||
//Open a jPlayer window and play the audio clip.
|
||||
$menu["play"] = array("name"=> "Play", "icon" => "big_play");
|
||||
|
||||
$this->view->items = $menu;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ class PlaylistController extends Zend_Controller_Action
|
|||
->addActionContext('get-playlist-fades', 'json')
|
||||
->addActionContext('set-playlist-name', 'json')
|
||||
->addActionContext('set-playlist-description', 'json')
|
||||
->addActionContext('playlist-preview', 'json')
|
||||
->addActionContext('get-playlist', 'json')
|
||||
->initContext();
|
||||
|
||||
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
|
||||
|
@ -196,17 +198,25 @@ class PlaylistController extends Zend_Controller_Action
|
|||
}
|
||||
}
|
||||
|
||||
public function audioPreviewPlayerAction()
|
||||
public function playlistPreviewAction()
|
||||
{
|
||||
$fileID = $this->_getParam('fileID');
|
||||
$playlistIndex = $this->_getParam('index');
|
||||
|
||||
$audioFileID = $this->_getParam('audioFileID');
|
||||
$audioFileArtist = $this->_getParam('audioFileArtist');
|
||||
$audioFileTitle = $this->_getParam('audioFileTitle');
|
||||
$playlistIndex = $this->_getParam('playlistIndex');
|
||||
$playlistID = $this->_getParam('playlistID');
|
||||
Logging::log($audioFileID);
|
||||
Logging::log($audioFileArtist);
|
||||
Logging::log($audioFileTitle);
|
||||
Logging::log($playlistIndex);
|
||||
Logging::log($playlistID);
|
||||
$request = $this->getRequest();
|
||||
$baseUrl = $request->getBaseUrl();
|
||||
|
||||
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/preview_jplayer.js?'.filemtime($baseDir.'/js/airtime/library/preview_jplayer.js'),'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/jquery.jplayer.min.js?'.filemtime($baseDir.'/js/jplayer/jquery.jplayer.min.js'),'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/preview_jplayer.js?'.filemtime($baseDir.'/js/jplayer/preview_jplayer.js'),'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/jplayer.playlist.min.js?'.filemtime($baseDir.'/js/jplayer/jplayer.playlist.min.js'),'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'/js/jplayer/skin/jplayer.audio-preview.blue.monday.css?'.filemtime($baseDir.'/js/jplayer/skin/jplayer.audio-preview.blue.monday.css'));
|
||||
$this->_helper->layout->setLayout('audioPlayer');
|
||||
|
||||
|
@ -216,11 +226,43 @@ class PlaylistController extends Zend_Controller_Action
|
|||
} else {
|
||||
$this->view->logo = "$baseUrl/css/images/airtime_logo_jp.png";
|
||||
}
|
||||
|
||||
$this->view->fileName = $fileID;
|
||||
Logging::log("The play list index is $playlistIndex");
|
||||
$this->view->audioFileID = $audioFileID;
|
||||
$this->view->audioFileArtist = $audioFileArtist;
|
||||
$this->view->audioFileTitle = $audioFileTitle;
|
||||
$this->view->playlistIndex= $playlistIndex;
|
||||
$this->view->playlistID = $playlistID;
|
||||
|
||||
}
|
||||
|
||||
public function getPlaylistAction(){
|
||||
|
||||
// disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$playlistID = $this->_getParam('playlistID');
|
||||
|
||||
if (!isset($playlistID)){
|
||||
return;
|
||||
}
|
||||
|
||||
$pl = new Application_Model_Playlist($playlistID);
|
||||
$result = Array();
|
||||
|
||||
foreach ( $pl->getContents() as $track ){
|
||||
$trackMap = array( 'title' => isset($track['CcFiles']['track_title'])?$track['CcFiles']['track_title']:"",
|
||||
'artist' => isset($track['CcFiles']['artist_name'])?$track['CcFiles']['artist_name']:"",
|
||||
'mp3' => '/api/get-media/fileID/'.$track['CcFiles']['gunid'].'.'.pathinfo($track['CcFiles']['filepath'], PATHINFO_EXTENSION),
|
||||
'id' => isset($track['id'])?$track['id']:"",
|
||||
'position' => isset($track['position'])?$track['position']:"",
|
||||
);
|
||||
$result[] = $trackMap;
|
||||
}
|
||||
|
||||
$this->_helper->json($result);
|
||||
}
|
||||
|
||||
public function addItemsAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids', array());
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<div id="content" class="jp-container">
|
||||
<span class='fileID'><?php echo "$this->fileName" ?></span>
|
||||
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
|
||||
<div id="jp_container_1" class="jp-audio">
|
||||
<div class="jp-type-single">
|
||||
<div class="jp-gui jp-interface">
|
||||
<ul class="jp-controls">
|
||||
<li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
|
||||
<li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
|
||||
<li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
|
||||
<li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
|
||||
<li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
|
||||
<li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
|
||||
</ul>
|
||||
<div class="jp-progress">
|
||||
<div class="jp-seek-bar">
|
||||
<div class="jp-play-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-volume-bar">
|
||||
<div class="jp-volume-bar-value"></div>
|
||||
</div>
|
||||
<div class="jp-time-holder">
|
||||
<div class="jp-current-time"></div>
|
||||
<div class="jp-duration"></div>
|
||||
|
||||
<ul class="jp-toggles">
|
||||
<li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
|
||||
<li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,50 @@
|
|||
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
|
||||
<div id="jp_container_1" class="jp-audio">
|
||||
<span class='audioFileID'><?php echo "$this->audioFileID" ?></span>
|
||||
<span class='audioFileTitle'><?php echo "$this->audioFileTitle" ?></span>
|
||||
<span class='audioFileArtist'><?php echo "$this->audioFileArtist" ?></span>
|
||||
<span class='playlistID'><?php echo "$this->playlistID" ?></span>
|
||||
<span class='playlistIndex'><?php echo "$this->playlistIndex" ?></span>
|
||||
|
||||
<div class="jp-type-playlist">
|
||||
<div class="jp-gui jp-interface">
|
||||
<ul class="jp-controls">
|
||||
<li><a href="" class="jp-previous" tabindex="1">previous</a></li>
|
||||
<li><a href="" class="jp-play" tabindex="1">play</a></li>
|
||||
<li><a href="" class="jp-pause" tabindex="1">pause</a></li>
|
||||
<li><a href="" class="jp-next" tabindex="1">next</a></li>
|
||||
<li><a href="" class="jp-stop" tabindex="1">stop</a></li>
|
||||
<li><a href="" class="jp-mute" tabindex="1" title="mute">mute</a></li>
|
||||
<li><a href="" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
|
||||
<li><a href="" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
|
||||
</ul>
|
||||
<div class="jp-progress">
|
||||
<div class="jp-seek-bar">
|
||||
<div class="jp-play-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-volume-bar">
|
||||
<div class="jp-volume-bar-value"></div>
|
||||
</div>
|
||||
<div class="jp-time-holder">
|
||||
<div class="jp-current-time"></div>
|
||||
<div class="jp-duration"></div>
|
||||
</div>
|
||||
<ul class="jp-toggles">
|
||||
<li><a href="" class="jp-shuffle" tabindex="1" title="shuffle">shuffle</a></li>
|
||||
<li><a href="" class="jp-shuffle-off" tabindex="1" title="shuffle off">shuffle off</a></li>
|
||||
<li><a href="" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
|
||||
<li><a href="" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="jp-playlist">
|
||||
<ul>
|
||||
<li></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="jp-no-solution">
|
||||
<span>Update Required</span>
|
||||
To play the media you will need to either update your browser to a recent version or update your <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash plugin</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -160,7 +160,12 @@
|
|||
|
||||
//add the play function to the library_type td
|
||||
$(nRow).find('td.library_type').click(function(){
|
||||
open_audio_preview(aData.audioFile, aData.id);
|
||||
if (aData.ftype === 'playlist' && aData.length !== '0.0'){
|
||||
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_
|
||||
open_playlist_preview(aData.audioFile, "", "", playlistIndex, 0);
|
||||
} else if (aData.ftype === 'audioclip') {
|
||||
open_playlist_preview(aData.audioFile, aData.track_title, aData.artist_name);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -360,7 +365,12 @@
|
|||
//define a play callback.
|
||||
if (oItems.play !== undefined) {
|
||||
callback = function() {
|
||||
open_audio_preview(data.audioFile, data.id);
|
||||
if (data.ftype === 'playlist' && data.length !== '0.0'){
|
||||
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_
|
||||
open_playlist_preview(data.audioFile, "", "", playlistIndex, 0);
|
||||
} else if (data.ftype === 'audioclip') {
|
||||
open_playlist_preview(data.audioFile, data.track_title, data.artist_name);
|
||||
}
|
||||
};
|
||||
oItems.play.callback = callback;
|
||||
}
|
||||
|
@ -634,24 +644,37 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var audio_preview_window = null;
|
||||
var preview_window = null;
|
||||
|
||||
function open_audio_preview(fileID, index) {
|
||||
url = 'Playlist/audio-preview-player/fileID/'+fileID+'/index/'+index;
|
||||
function openAudioPreview(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var audioFileID = $(this).attr('audioFile');
|
||||
var playlistID = $('#pl_id:first').attr('value');
|
||||
var playlistIndex = $(this).parent().parent().attr('id');
|
||||
playlistIndex = playlistIndex.substring(4); //remove the spl_
|
||||
|
||||
open_playlist_preview(audioFileID, "", "", playlistID, playlistIndex);
|
||||
}
|
||||
|
||||
function open_playlist_preview(audioFileID, audioFileTitle, audioFileArtist, playlistID, playlistIndex) {
|
||||
if (playlistIndex != undefined)
|
||||
url = 'Playlist/playlist-preview/audioFileID/'+audioFileID+'/playlistIndex/'+playlistIndex+'/playlistID/'+playlistID;
|
||||
else
|
||||
url = 'Playlist/playlist-preview/audioFileID/'+audioFileID+'/audioFileArtist/'+audioFileArtist+'/audioFileTitle/'+audioFileTitle;
|
||||
//$.post(baseUri+'Playlist/audio-preview-player', {fileName: fileName, cueIn: cueIn, cueOut: cueOut, fadeIn: fadeIn, fadeInFileName: fadeInFileName, fadeOut: fadeOut, fadeOutFileName: fadeOutFileName})
|
||||
if (audio_preview_window == null || audio_preview_window.closed){
|
||||
audio_preview_window = window.open(url, 'Audio Player', 'width=400,height=95');
|
||||
} else if (!audio_preview_window.closed) {
|
||||
audio_preview_window.play(fileID);
|
||||
} else {
|
||||
console.log("something else : "+baseUrl+url);
|
||||
if (preview_window == null || preview_window.closed || playlistIndex === undefined){
|
||||
preview_window = window.open(url, 'Audio Player', 'width=450,height=800');
|
||||
} else if (!preview_window.closed) {
|
||||
preview_window.playAll(playlistID, playlistIndex);
|
||||
}
|
||||
|
||||
//Set the play button to pause.
|
||||
//var elemID = "spl_"+elemIndexString;
|
||||
//$('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause");
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
var fileID = $(".fileID").text();
|
||||
play(fileID);
|
||||
});
|
||||
|
||||
function play(fileID){
|
||||
var uri = "/api/get-media/fileID/" + fileID;
|
||||
var ext = getFileExt(fileID);
|
||||
|
||||
|
||||
var media;
|
||||
var supplied;
|
||||
if (ext == "ogg"){
|
||||
media = {oga:uri};
|
||||
supplied = "oga";
|
||||
} else {
|
||||
media = {mp3:uri};
|
||||
supplied = "mp3";
|
||||
}
|
||||
|
||||
$("#jquery_jplayer_1").jPlayer("destroy");
|
||||
$.jPlayer.timeFormat.showHour = true;
|
||||
$("#jquery_jplayer_1").jPlayer({
|
||||
ready: function () {
|
||||
|
||||
$(this).jPlayer("setMedia", media).jPlayer("play");
|
||||
|
||||
},
|
||||
swfPath: "/js/jplayer",
|
||||
cssSelectorAncestor: '#jp_container_1',
|
||||
wmode: "window"
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -244,15 +244,6 @@ var AIRTIME = (function(AIRTIME){
|
|||
highlightActive(icon);
|
||||
}
|
||||
}
|
||||
|
||||
function openAudioPreview(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var audioFile = $(this).attr('audioFile');
|
||||
var id = "";
|
||||
|
||||
open_audio_preview(audioFile, id);
|
||||
}
|
||||
|
||||
function editName() {
|
||||
var nameElement = $(this),
|
||||
|
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Playlist Object for the jPlayer Plugin
|
||||
* http://www.jplayer.org
|
||||
*
|
||||
* Copyright (c) 2009 - 2011 Happyworm Ltd
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* - http://www.opensource.org/licenses/mit-license.php
|
||||
* - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Author: Mark J Panaghiston
|
||||
* Version: 2.1.0 (jPlayer 2.1.0)
|
||||
* Date: 1st September 2011
|
||||
*/
|
||||
|
||||
/* Code verified using http://www.jshint.com/ */
|
||||
/*jshint asi:false, bitwise:false, boss:false, browser:true, curly:true, debug:false, eqeqeq:true, eqnull:false, evil:false, forin:false, immed:false, jquery:true, laxbreak:false, newcap:true, noarg:true, noempty:true, nonew:true, nomem:false, onevar:false, passfail:false, plusplus:false, regexp:false, undef:true, sub:false, strict:false, white:false */
|
||||
/*global jPlayerPlaylist: true, jQuery:false, alert:false */
|
||||
|
||||
(function($, undefined) {
|
||||
|
||||
jPlayerPlaylist = function(cssSelector, playlist, options) {
|
||||
var self = this;
|
||||
|
||||
this.current = 0;
|
||||
this.loop = false; // Flag used with the jPlayer repeat event
|
||||
this.shuffled = false;
|
||||
this.removing = false; // Flag is true during remove animation, disabling the remove() method until complete.
|
||||
|
||||
this.cssSelector = $.extend({}, this._cssSelector, cssSelector); // Object: Containing the css selectors for jPlayer and its cssSelectorAncestor
|
||||
this.options = $.extend(true, {}, this._options, options); // Object: The jPlayer constructor options for this playlist and the playlist options
|
||||
|
||||
this.playlist = []; // Array of Objects: The current playlist displayed (Un-shuffled or Shuffled)
|
||||
this.original = []; // Array of Objects: The original playlist
|
||||
|
||||
this._initPlaylist(playlist); // Copies playlist to this.original. Then mirrors this.original to this.playlist. Creating two arrays, where the element pointers match. (Enables pointer comparison.)
|
||||
|
||||
// Setup the css selectors for the extra interface items used by the playlist.
|
||||
this.cssSelector.title = this.cssSelector.cssSelectorAncestor + " .jp-title"; // Note that the text is written to the decendant li node.
|
||||
this.cssSelector.playlist = this.cssSelector.cssSelectorAncestor + " .jp-playlist";
|
||||
this.cssSelector.next = this.cssSelector.cssSelectorAncestor + " .jp-next";
|
||||
this.cssSelector.previous = this.cssSelector.cssSelectorAncestor + " .jp-previous";
|
||||
this.cssSelector.shuffle = this.cssSelector.cssSelectorAncestor + " .jp-shuffle";
|
||||
this.cssSelector.shuffleOff = this.cssSelector.cssSelectorAncestor + " .jp-shuffle-off";
|
||||
|
||||
// Override the cssSelectorAncestor given in options
|
||||
this.options.cssSelectorAncestor = this.cssSelector.cssSelectorAncestor;
|
||||
|
||||
// Override the default repeat event handler
|
||||
this.options.repeat = function(event) {
|
||||
self.loop = event.jPlayer.options.loop;
|
||||
};
|
||||
|
||||
// Create a ready event handler to initialize the playlist
|
||||
$(this.cssSelector.jPlayer).bind($.jPlayer.event.ready, function(event) {
|
||||
self._init();
|
||||
});
|
||||
|
||||
// Create an ended event handler to move to the next item
|
||||
$(this.cssSelector.jPlayer).bind($.jPlayer.event.ended, function(event) {
|
||||
self.next();
|
||||
});
|
||||
|
||||
// Create a play event handler to pause other instances
|
||||
$(this.cssSelector.jPlayer).bind($.jPlayer.event.play, function(event) {
|
||||
$(this).jPlayer("pauseOthers");
|
||||
});
|
||||
|
||||
// Create a resize event handler to show the title in full screen mode.
|
||||
$(this.cssSelector.jPlayer).bind($.jPlayer.event.resize, function(event) {
|
||||
if(event.jPlayer.options.fullScreen) {
|
||||
$(self.cssSelector.title).show();
|
||||
} else {
|
||||
$(self.cssSelector.title).hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Create click handlers for the extra buttons that do playlist functions.
|
||||
$(this.cssSelector.previous).click(function() {
|
||||
self.previous();
|
||||
$(this).blur();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(this.cssSelector.next).click(function() {
|
||||
self.next();
|
||||
$(this).blur();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(this.cssSelector.shuffle).click(function() {
|
||||
self.shuffle(true);
|
||||
return false;
|
||||
});
|
||||
$(this.cssSelector.shuffleOff).click(function() {
|
||||
self.shuffle(false);
|
||||
return false;
|
||||
}).hide();
|
||||
|
||||
// Put the title in its initial display state
|
||||
if(!this.options.fullScreen) {
|
||||
$(this.cssSelector.title).hide();
|
||||
}
|
||||
|
||||
// Remove the empty <li> from the page HTML. Allows page to be valid HTML, while not interfereing with display animations
|
||||
$(this.cssSelector.playlist + " ul").empty();
|
||||
|
||||
// Create .live() handlers for the playlist items along with the free media and remove controls.
|
||||
this._createItemHandlers();
|
||||
|
||||
// Instance jPlayer
|
||||
$(this.cssSelector.jPlayer).jPlayer(this.options);
|
||||
};
|
||||
|
||||
jPlayerPlaylist.prototype = {
|
||||
_cssSelector: { // static object, instanced in constructor
|
||||
jPlayer: "#jquery_jplayer_1",
|
||||
cssSelectorAncestor: "#jp_container_1"
|
||||
},
|
||||
_options: { // static object, instanced in constructor
|
||||
playlistOptions: {
|
||||
autoPlay: false,
|
||||
loopOnPrevious: false,
|
||||
shuffleOnLoop: true,
|
||||
enableRemoveControls: false,
|
||||
displayTime: 'slow',
|
||||
addTime: 'fast',
|
||||
removeTime: 'fast',
|
||||
shuffleTime: 'slow',
|
||||
itemClass: "jp-playlist-item",
|
||||
freeGroupClass: "jp-free-media",
|
||||
freeItemClass: "jp-playlist-item-free",
|
||||
removeItemClass: "jp-playlist-item-remove"
|
||||
}
|
||||
},
|
||||
option: function(option, value) { // For changing playlist options only
|
||||
if(value === undefined) {
|
||||
return this.options.playlistOptions[option];
|
||||
}
|
||||
|
||||
this.options.playlistOptions[option] = value;
|
||||
|
||||
switch(option) {
|
||||
case "enableRemoveControls":
|
||||
this._updateControls();
|
||||
break;
|
||||
case "itemClass":
|
||||
case "freeGroupClass":
|
||||
case "freeItemClass":
|
||||
case "removeItemClass":
|
||||
this._refresh(true); // Instant
|
||||
this._createItemHandlers();
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
_init: function() {
|
||||
var self = this;
|
||||
this._refresh(function() {
|
||||
if(self.options.playlistOptions.autoPlay) {
|
||||
self.play(self.current);
|
||||
} else {
|
||||
self.select(self.current);
|
||||
}
|
||||
});
|
||||
},
|
||||
_initPlaylist: function(playlist) {
|
||||
this.current = 0;
|
||||
this.shuffled = false;
|
||||
this.removing = false;
|
||||
this.original = $.extend(true, [], playlist); // Copy the Array of Objects
|
||||
this._originalPlaylist();
|
||||
},
|
||||
_originalPlaylist: function() {
|
||||
var self = this;
|
||||
this.playlist = [];
|
||||
// Make both arrays point to the same object elements. Gives us 2 different arrays, each pointing to the same actual object. ie., Not copies of the object.
|
||||
$.each(this.original, function(i,v) {
|
||||
self.playlist[i] = self.original[i];
|
||||
});
|
||||
},
|
||||
_refresh: function(instant) {
|
||||
/* instant: Can be undefined, true or a function.
|
||||
* undefined -> use animation timings
|
||||
* true -> no animation
|
||||
* function -> use animation timings and excute function at half way point.
|
||||
*/
|
||||
var self = this;
|
||||
|
||||
if(instant && !$.isFunction(instant)) {
|
||||
$(this.cssSelector.playlist + " ul").empty();
|
||||
$.each(this.playlist, function(i,v) {
|
||||
$(self.cssSelector.playlist + " ul").append(self._createListItem(self.playlist[i]));
|
||||
});
|
||||
this._updateControls();
|
||||
} else {
|
||||
var displayTime = $(this.cssSelector.playlist + " ul").children().length ? this.options.playlistOptions.displayTime : 0;
|
||||
|
||||
$(this.cssSelector.playlist + " ul").slideUp(displayTime, function() {
|
||||
var $this = $(this);
|
||||
$(this).empty();
|
||||
|
||||
$.each(self.playlist, function(i,v) {
|
||||
$this.append(self._createListItem(self.playlist[i]));
|
||||
});
|
||||
self._updateControls();
|
||||
if($.isFunction(instant)) {
|
||||
instant();
|
||||
}
|
||||
if(self.playlist.length) {
|
||||
$(this).slideDown(self.options.playlistOptions.displayTime);
|
||||
} else {
|
||||
$(this).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_createListItem: function(media) {
|
||||
var self = this;
|
||||
|
||||
// Wrap the <li> contents in a <div>
|
||||
var listItem = "<li><div>";
|
||||
|
||||
// Create remove control
|
||||
listItem += "<a href='javascript:;' class='" + this.options.playlistOptions.removeItemClass + "'>×</a>";
|
||||
|
||||
// Create links to free media
|
||||
if(media.free) {
|
||||
var first = true;
|
||||
listItem += "<span class='" + this.options.playlistOptions.freeGroupClass + "'>(";
|
||||
$.each(media, function(property,value) {
|
||||
if($.jPlayer.prototype.format[property]) { // Check property is a media format.
|
||||
if(first) {
|
||||
first = false;
|
||||
} else {
|
||||
listItem += " | ";
|
||||
}
|
||||
listItem += "<a class='" + self.options.playlistOptions.freeItemClass + "' href='" + value + "' tabindex='1'>" + property + "</a>";
|
||||
}
|
||||
});
|
||||
listItem += ")</span>";
|
||||
}
|
||||
|
||||
// The title is given next in the HTML otherwise the float:right on the free media corrupts in IE6/7
|
||||
listItem += "<a href='javascript:;' class='" + this.options.playlistOptions.itemClass + "' tabindex='1'>" + media.title + (media.artist ? " <span class='jp-artist'>by " + media.artist + "</span>" : "") + "</a>";
|
||||
listItem += "</div></li>";
|
||||
|
||||
return listItem;
|
||||
},
|
||||
_createItemHandlers: function() {
|
||||
var self = this;
|
||||
// Create .live() handlers for the playlist items
|
||||
$(this.cssSelector.playlist + " a." + this.options.playlistOptions.itemClass).die("click").live("click", function() {
|
||||
var index = $(this).parent().parent().index();
|
||||
if(self.current !== index) {
|
||||
self.play(index);
|
||||
} else {
|
||||
$(self.cssSelector.jPlayer).jPlayer("play");
|
||||
}
|
||||
$(this).blur();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Create .live() handlers that disable free media links to force access via right click
|
||||
$(self.cssSelector.playlist + " a." + this.options.playlistOptions.freeItemClass).die("click").live("click", function() {
|
||||
$(this).parent().parent().find("." + self.options.playlistOptions.itemClass).click();
|
||||
$(this).blur();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Create .live() handlers for the remove controls
|
||||
$(self.cssSelector.playlist + " a." + this.options.playlistOptions.removeItemClass).die("click").live("click", function() {
|
||||
var index = $(this).parent().parent().index();
|
||||
self.remove(index);
|
||||
$(this).blur();
|
||||
return false;
|
||||
});
|
||||
},
|
||||
_updateControls: function() {
|
||||
if(this.options.playlistOptions.enableRemoveControls) {
|
||||
$(this.cssSelector.playlist + " ." + this.options.playlistOptions.removeItemClass).show();
|
||||
} else {
|
||||
$(this.cssSelector.playlist + " ." + this.options.playlistOptions.removeItemClass).hide();
|
||||
}
|
||||
if(this.shuffled) {
|
||||
$(this.cssSelector.shuffleOff).show();
|
||||
$(this.cssSelector.shuffle).hide();
|
||||
} else {
|
||||
$(this.cssSelector.shuffleOff).hide();
|
||||
$(this.cssSelector.shuffle).show();
|
||||
}
|
||||
},
|
||||
_highlight: function(index) {
|
||||
if(this.playlist.length && index !== undefined) {
|
||||
$(this.cssSelector.playlist + " .jp-playlist-current").removeClass("jp-playlist-current");
|
||||
$(this.cssSelector.playlist + " li:nth-child(" + (index + 1) + ")").addClass("jp-playlist-current").find(".jp-playlist-item").addClass("jp-playlist-current");
|
||||
$(this.cssSelector.title + " li").html(this.playlist[index].title + (this.playlist[index].artist ? " <span class='jp-artist'>by " + this.playlist[index].artist + "</span>" : ""));
|
||||
}
|
||||
},
|
||||
setPlaylist: function(playlist) {
|
||||
this._initPlaylist(playlist);
|
||||
this._init();
|
||||
},
|
||||
add: function(media, playNow) {
|
||||
$(this.cssSelector.playlist + " ul").append(this._createListItem(media)).find("li:last-child").hide().slideDown(this.options.playlistOptions.addTime);
|
||||
this._updateControls();
|
||||
this.original.push(media);
|
||||
this.playlist.push(media); // Both array elements share the same object pointer. Comforms with _initPlaylist(p) system.
|
||||
|
||||
if(playNow) {
|
||||
this.play(this.playlist.length - 1);
|
||||
} else {
|
||||
if(this.original.length === 1) {
|
||||
this.select(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
remove: function(index) {
|
||||
var self = this;
|
||||
|
||||
if(index === undefined) {
|
||||
this._initPlaylist([]);
|
||||
this._refresh(function() {
|
||||
$(self.cssSelector.jPlayer).jPlayer("clearMedia");
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
|
||||
if(this.removing) {
|
||||
return false;
|
||||
} else {
|
||||
index = (index < 0) ? self.original.length + index : index; // Negative index relates to end of array.
|
||||
if(0 <= index && index < this.playlist.length) {
|
||||
this.removing = true;
|
||||
|
||||
$(this.cssSelector.playlist + " li:nth-child(" + (index + 1) + ")").slideUp(this.options.playlistOptions.removeTime, function() {
|
||||
$(this).remove();
|
||||
|
||||
if(self.shuffled) {
|
||||
var item = self.playlist[index];
|
||||
$.each(self.original, function(i,v) {
|
||||
if(self.original[i] === item) {
|
||||
self.original.splice(i, 1);
|
||||
return false; // Exit $.each
|
||||
}
|
||||
});
|
||||
self.playlist.splice(index, 1);
|
||||
} else {
|
||||
self.original.splice(index, 1);
|
||||
self.playlist.splice(index, 1);
|
||||
}
|
||||
|
||||
if(self.original.length) {
|
||||
if(index === self.current) {
|
||||
self.current = (index < self.original.length) ? self.current : self.original.length - 1; // To cope when last element being selected when it was removed
|
||||
self.select(self.current);
|
||||
} else if(index < self.current) {
|
||||
self.current--;
|
||||
}
|
||||
} else {
|
||||
$(self.cssSelector.jPlayer).jPlayer("clearMedia");
|
||||
self.current = 0;
|
||||
self.shuffled = false;
|
||||
self._updateControls();
|
||||
}
|
||||
|
||||
self.removing = false;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
select: function(index) {
|
||||
index = (index < 0) ? this.original.length + index : index; // Negative index relates to end of array.
|
||||
if(0 <= index && index < this.playlist.length) {
|
||||
this.current = index;
|
||||
this._highlight(index);
|
||||
$(this.cssSelector.jPlayer).jPlayer("setMedia", this.playlist[this.current]);
|
||||
} else {
|
||||
this.current = 0;
|
||||
}
|
||||
},
|
||||
play: function(index) {
|
||||
index = (index < 0) ? this.original.length + index : index; // Negative index relates to end of array.
|
||||
if(0 <= index && index < this.playlist.length) {
|
||||
if(this.playlist.length) {
|
||||
this.select(index);
|
||||
$(this.cssSelector.jPlayer).jPlayer("play");
|
||||
}
|
||||
} else if(index === undefined) {
|
||||
$(this.cssSelector.jPlayer).jPlayer("play");
|
||||
}
|
||||
},
|
||||
pause: function() {
|
||||
$(this.cssSelector.jPlayer).jPlayer("pause");
|
||||
},
|
||||
next: function() {
|
||||
var index = (this.current + 1 < this.playlist.length) ? this.current + 1 : 0;
|
||||
|
||||
if(this.loop) {
|
||||
// See if we need to shuffle before looping to start, and only shuffle if more than 1 item.
|
||||
if(index === 0 && this.shuffled && this.options.playlistOptions.shuffleOnLoop && this.playlist.length > 1) {
|
||||
this.shuffle(true, true); // playNow
|
||||
} else {
|
||||
this.play(index);
|
||||
}
|
||||
} else {
|
||||
// The index will be zero if it just looped round
|
||||
if(index > 0) {
|
||||
this.play(index);
|
||||
}
|
||||
}
|
||||
},
|
||||
previous: function() {
|
||||
var index = (this.current - 1 >= 0) ? this.current - 1 : this.playlist.length - 1;
|
||||
|
||||
if(this.loop && this.options.playlistOptions.loopOnPrevious || index < this.playlist.length - 1) {
|
||||
this.play(index);
|
||||
}
|
||||
},
|
||||
shuffle: function(shuffled, playNow) {
|
||||
var self = this;
|
||||
|
||||
if(shuffled === undefined) {
|
||||
shuffled = !this.shuffled;
|
||||
}
|
||||
|
||||
if(shuffled || shuffled !== this.shuffled) {
|
||||
|
||||
$(this.cssSelector.playlist + " ul").slideUp(this.options.playlistOptions.shuffleTime, function() {
|
||||
self.shuffled = shuffled;
|
||||
if(shuffled) {
|
||||
self.playlist.sort(function() {
|
||||
return 0.5 - Math.random();
|
||||
});
|
||||
} else {
|
||||
self._originalPlaylist();
|
||||
}
|
||||
self._refresh(true); // Instant
|
||||
|
||||
if(playNow || !$(self.cssSelector.jPlayer).data("jPlayer").status.paused) {
|
||||
self.play(0);
|
||||
} else {
|
||||
self.select(0);
|
||||
}
|
||||
|
||||
$(this).slideDown(self.options.playlistOptions.shuffleTime);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
|
@ -0,0 +1,93 @@
|
|||
var playlist_jplayer;
|
||||
var idToPostionLookUp;
|
||||
|
||||
$(document).ready(function(){
|
||||
var audioFileID = $('.audioFileID').text();
|
||||
var playlistID = $('.playlistID').text();
|
||||
var playlistIndex = $('.playlistIndex').text();
|
||||
console.log('in the ready');
|
||||
playlist_jplayer = new jPlayerPlaylist({
|
||||
jPlayer: "#jquery_jplayer_1",
|
||||
cssSelectorAncestor: "#jp_container_1"
|
||||
},[], //array of songs will be filled with below's json call
|
||||
{
|
||||
swfPath: "/js/jplayer",
|
||||
supplied: "mp3, oga",
|
||||
wmode: "window"
|
||||
});
|
||||
|
||||
$.jPlayer.timeFormat.showHour = true;
|
||||
|
||||
if (playlistID != undefined && playlistID !== "")
|
||||
playAll(playlistID, playlistIndex);
|
||||
else
|
||||
playOne(audioFileID);
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets up the jPlayerPlaylist to play.
|
||||
* - Get the playlist info based on the playlistID give.
|
||||
* - Update the playlistIndex to the position in the pllist to start playing.
|
||||
* - Select the element played from and start playing. If playlist is null then start at index 0.
|
||||
**/
|
||||
function playAll(playlistID, playlistIndex) {
|
||||
var viewsPlaylistID = $('.playlistID').text();
|
||||
|
||||
if ( idToPostionLookUp !== undefined && viewsPlaylistID == playlistID ) {
|
||||
play(playlistIndex);
|
||||
}else {
|
||||
idToPostionLookUp = Array();
|
||||
$.getJSON("/playlist/get-playlist/playlistID/"+playlistID, function(data){ // get the JSON array produced by my PHP
|
||||
var myPlaylist = new Array();
|
||||
var media;
|
||||
var index;
|
||||
for(index in data){
|
||||
if (data[index]['mp3'] != 'undefined'){
|
||||
media = {title: data[index]['title'],
|
||||
artist: data[index]['artist'],
|
||||
mp3:data[index]['mp3']
|
||||
};
|
||||
}else if (data[index]['ogg'] != 'undefined') {
|
||||
media = {title: data[index]['title'],
|
||||
artist: data[index]['artist'],
|
||||
oga:data[index]['ogg']
|
||||
};
|
||||
}
|
||||
myPlaylist[index] = media;
|
||||
|
||||
idToPostionLookUp[data[index]['id']] = data[index]['position'];
|
||||
}
|
||||
playlist_jplayer.setPlaylist(myPlaylist);
|
||||
playlist_jplayer.option("autoPlay", true);
|
||||
play(playlistIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function play(playlistIndex){
|
||||
playlistIndex = idToPostionLookUp[playlistIndex];
|
||||
playlist_jplayer.play(playlistIndex);
|
||||
}
|
||||
|
||||
function playOne(audioFileID) {
|
||||
var playlist = new Array();
|
||||
var fileExtensioin = audioFileID.split('.').pop();
|
||||
|
||||
if (fileExtensioin === 'mp3') {
|
||||
media = {title: $('.audioFileTitle').text() !== 'null' ?$('.audioFileTitle').text():"",
|
||||
artist: $('.audioFileArtist').text() !== 'null' ?$('.audioFileArtist').text():"",
|
||||
mp3:"/api/get-media/fileID/"+audioFileID
|
||||
};
|
||||
}else if (fileExtensioin === 'ogg' ) {
|
||||
media = {title: $('.audioFileTitle').text() != 'null' ?$('.audioFileTitle').text():"",
|
||||
artist: $('.audioFileArtist').text() != 'null' ?$('.audioFileArtist').text():"",
|
||||
oga:"/api/get-media/fileID/"+audioFileID
|
||||
};
|
||||
}
|
||||
playlist[0] = media;
|
||||
|
||||
playlist_jplayer.setPlaylist(playlist);
|
||||
playlist_jplayer.option("autoPlay", true);
|
||||
playlist_jplayer.play(0);
|
||||
}
|
|
@ -30,6 +30,7 @@ div.jp-video {
|
|||
background-color:#eee;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
div.jp-audio {
|
||||
width:420px;
|
||||
}
|
||||
|
@ -88,8 +89,20 @@ div.jp-video div.jp-interface {
|
|||
border-top:1px solid #009be3;
|
||||
}
|
||||
|
||||
/* Used to hide the filename field **/
|
||||
span.fileID {
|
||||
/* Used to hide non-ui fields **/
|
||||
span.audioFileID {
|
||||
display:none;
|
||||
}
|
||||
span.audioFileTitle {
|
||||
display:none;
|
||||
}
|
||||
span.audioFileArtist {
|
||||
display:none;
|
||||
}
|
||||
span.playlistID {
|
||||
display:none;
|
||||
}
|
||||
span.playlistIndex {
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue