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.

Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

Conflicts:
	airtime_mvc/application/controllers/LibraryController.php
	airtime_mvc/public/js/airtime/library/library.js
This commit is contained in:
Daniel 2012-03-12 10:23:50 -04:00
commit d713f830cd
61 changed files with 5112 additions and 200 deletions

View file

@ -1,4 +1,4 @@
var AIRTIME = (function(AIRTIME){
var AIRTIME = (function(AIRTIME) {
var mod,
libraryInit;
@ -42,14 +42,17 @@
};
libraryInit = function() {
var oTable;
var oTable,
libContentDiv = $("#library_content");
tableHeight = libContentDiv.height() - 140;
oTable = $('#library_display').dataTable( {
//put hidden columns at the top to insure they can never be visible on the table through column reordering.
"aoColumns": [
/* Checkbox */ {"sTitle": "<input type='checkbox' name='pl_cb_all'>", "mDataProp": "checkbox", "bSortable": false, "bSearchable": false, "sWidth": "25px", "sClass": "library_checkbox"},
/* Type */ {"sTitle": "", "mDataProp": "image", "bSearchable": false, "sWidth": "25px", "sClass": "library_type", "iDataSort": 2},
/* ftype */ {"sTitle": "", "mDataProp": "ftype", "bSearchable": false, "bVisible": false},
/* Checkbox */ {"sTitle": "<input type='checkbox' name='pl_cb_all'>", "mDataProp": "checkbox", "bSortable": false, "bSearchable": false, "sWidth": "25px", "sClass": "library_checkbox"},
/* Type */ {"sTitle": "", "mDataProp": "image", "bSearchable": false, "sWidth": "25px", "sClass": "library_type", "iDataSort": 0},
/* Title */ {"sTitle": "Title", "mDataProp": "track_title", "sClass": "library_title"},
/* Creator */ {"sTitle": "Creator", "mDataProp": "artist_name", "sClass": "library_creator"},
/* Album */ {"sTitle": "Album", "mDataProp": "album_title", "sClass": "library_album"},
@ -58,7 +61,7 @@
/* Length */ {"sTitle": "Length", "mDataProp": "length", "sClass": "library_length", "sWidth": "80px"},
/* Upload Time */ {"sTitle": "Uploaded", "mDataProp": "utime", "sClass": "library_upload_time"},
/* Last Modified */ {"sTitle": "Last Modified", "mDataProp": "mtime", "bVisible": false, "sClass": "library_modified_time"},
/* Track Number */ {"sTitle": "Track", "mDataProp": "track_number", "bSearchable": false, "bVisible": false, "sClass": "library_track"},
/* Track Number */ {"sTitle": "Track", "mDataProp": "track_number", "bSearchable": false, "bVisible": false, "sClass": "library_track", "sWidth": "65px"},
/* Mood */ {"sTitle": "Mood", "mDataProp": "mood", "bSearchable": false, "bVisible": false, "sClass": "library_mood"},
/* BPM */ {"sTitle": "BPM", "mDataProp": "bpm", "bSearchable": false, "bVisible": false, "sClass": "library_bpm"},
/* Composer */ {"sTitle": "Composer", "mDataProp": "composer", "bSearchable": false, "bVisible": false, "sClass": "library_composer"},
@ -232,9 +235,9 @@
"oLanguage": {
"sSearch": ""
},
// R = ColReorder, C = ColVis, T = TableTools
"sDom": 'Rl<"#library_display_type">fr<"H"T<"library_toolbar"C>>t<"F"ip>',
"sDom": 'Rl<"#library_display_type">fr<"H"T<"library_toolbar"C>><"dataTables_scrolling"t><"F"ip>',
"oTableTools": {
"sRowSelect": "multi",
@ -290,6 +293,8 @@
});
oTable.fnSetFilteringDelay(350);
libContentDiv.find(".dataTables_scrolling").css("max-height", tableHeight);
AIRTIME.library.events.setupLibraryToolbar(oTable);
@ -469,9 +474,9 @@
return AIRTIME;
}(AIRTIME || {}));
}(AIRTIME || {}));
function addToolBarButtonsLibrary(aButtons) {
function addToolBarButtonsLibrary(aButtons) {
var i,
length = aButtons.length,
libToolBar = $(".library_toolbar"),
@ -511,9 +516,9 @@
}(i));
}
}
}
function checkImportStatus(){
function checkImportStatus(){
$.getJSON('/Preference/is-import-in-progress', function(data){
var div = $('#import_status');
if (data == true){
@ -523,9 +528,9 @@
div.hide();
}
});
}
}
function addProgressIcon(id) {
function addProgressIcon(id) {
var tr = $("#au_"+id),
span;
@ -539,9 +544,9 @@
tr.find("td.library_title")
.append('<span class="small-icon progress"></span>');
}
}
}
function checkSCUploadStatus(){
function checkSCUploadStatus(){
var url = '/Library/get-upload-to-soundcloud-status';
@ -563,9 +568,9 @@
}
});
});
}
}
function addQtipToSCIcons(){
function addQtipToSCIcons(){
$(".progress, .soundcloud, .sc-error").live('mouseover', function(){
var id = $(this).parent().parent().data("aData").id;
@ -644,8 +649,7 @@
});
}
});
}
}
var audio_preview_window = null;
@ -662,4 +666,3 @@ function open_audio_preview(fileID, index) {
return false;
}

View file

@ -1 +1,16 @@
$(document).ready(AIRTIME.library.libraryInit);
$(document).ready(function() {
var viewport = AIRTIME.utilities.findViewportDimensions(),
lib = $("#library_content"),
pl = $("#side_playlist"),
widgetHeight = viewport.height - 185,
width = Math.floor(viewport.width - 110);
lib.height(widgetHeight)
.width(Math.floor(width * 0.55));
pl.height(widgetHeight)
.width(Math.floor(width * 0.45));
AIRTIME.library.libraryInit();
});

View file

@ -0,0 +1,133 @@
var AIRTIME = (function(AIRTIME) {
var mod;
if (AIRTIME.history === undefined) {
AIRTIME.history = {};
}
mod = AIRTIME.history;
mod.historyTable = function() {
var oTable,
historyContentDiv = $("#history_content"),
historyTableDiv = historyContentDiv.find("#history_table"),
tableHeight = historyContentDiv.height() - 140,
fnServerData;
fnServerData = function ( sSource, aoData, fnCallback ) {
if (fnServerData.hasOwnProperty("start")) {
aoData.push( { name: "start", value: fnServerData.start} );
}
if (fnServerData.hasOwnProperty("end")) {
aoData.push( { name: "end", value: fnServerData.end} );
}
aoData.push( { name: "format", value: "json"} );
$.ajax( {
"dataType": 'json',
"type": "GET",
"url": sSource,
"data": aoData,
"success": fnCallback
} );
};
oTable = historyTableDiv.dataTable( {
"aoColumns": [
{"sTitle": "Title", "mDataProp": "title", "sClass": "his_title"}, /* Title */
{"sTitle": "Artist", "mDataProp": "artist", "sClass": "his_artist"}, /* Creator */
{"sTitle": "Played", "mDataProp": "played", "sClass": "his_artist"}, /* times played */
{"sTitle": "Length", "mDataProp": "length", "sClass": "his_length library_length"}, /* Length */
{"sTitle": "Composer", "mDataProp": "composer", "sClass": "his_composer"}, /* Composer */
{"sTitle": "Copyright", "mDataProp": "copyright", "sClass": "his_copyright"} /* Copyright */
],
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/Playouthistory/playout-history-feed",
"sAjaxDataProp": "history",
"fnServerData": fnServerData,
"oLanguage": {
"sSearch": ""
},
"aLengthMenu": [[50, 100, 500, -1], [50, 100, 500, "All"]],
"iDisplayLength": 50,
"sPaginationType": "full_numbers",
"bJQueryUI": true,
"bAutoWidth": true,
"sDom": 'lfr<"H"T><"dataTables_scrolling"t><"F"ip>',
"oTableTools": {
"sSwfPath": "/js/datatables/plugin/TableTools/swf/copy_cvs_xls_pdf.swf"
}
});
oTable.fnSetFilteringDelay(350);
return oTable;
};
return AIRTIME;
}(AIRTIME || {}));
$(document).ready(function(){
var viewport = AIRTIME.utilities.findViewportDimensions(),
history_content = $("#history_content"),
widgetHeight = viewport.height - 185,
screenWidth = Math.floor(viewport.width - 110),
oBaseDatePickerSettings,
oBaseTimePickerSettings,
oTable,
dateStartId = "#his_date_start",
timeStartId = "#his_time_start",
dateEndId = "#his_date_end",
timeEndId = "#his_time_end";
history_content
.height(widgetHeight)
.width(screenWidth);
oBaseDatePickerSettings = {
dateFormat: 'yy-mm-dd',
onSelect: function(sDate, oDatePicker) {
$(this).datepicker( "setDate", sDate );
}
};
oBaseTimePickerSettings = {
showPeriodLabels: false,
showCloseButton: true,
showLeadingZero: false,
defaultTime: '0:00'
};
oTable = AIRTIME.history.historyTable();
history_content.find(dateStartId).datepicker(oBaseDatePickerSettings);
history_content.find(timeStartId).timepicker(oBaseTimePickerSettings);
history_content.find(dateEndId).datepicker(oBaseDatePickerSettings);
history_content.find(timeEndId).timepicker(oBaseTimePickerSettings);
history_content.find("#his_submit").click(function(ev){
var fn,
oRange;
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId, dateEndId, timeEndId);
fn = oTable.fnSettings().fnServerData;
fn.start = oRange.start;
fn.end = oRange.end;
oTable.fnDraw();
});
});

View file

@ -100,15 +100,32 @@ function buildScheduleDialog (json) {
var dialog = $(json.dialog),
viewport = findViewportDimensions(),
height = viewport.height * 0.96,
width = viewport.width * 0.96,
fnServer = AIRTIME.showbuilder.fnServerData;
height = Math.floor(viewport.height * 0.96),
width = Math.floor(viewport.width * 0.96),
fnServer = AIRTIME.showbuilder.fnServerData,
//subtract padding in pixels
widgetWidth = width - 50,
libWidth = Math.floor(widgetWidth * 0.5),
builderWidth = Math.floor(widgetWidth * 0.5),
libLength,
libType,
libFilter;
dialog.find("#library_content")
.height(height - 110)
.width(libWidth);
dialog.find("#show_builder")
.height(height - 110)
.width(builderWidth);
dialog.dialog({
autoOpen: false,
title: json.title,
width: width,
height: height,
resizable: false,
draggable: false,
modal: true,
close: closeDialog,
buttons: {"Ok": function() {
@ -116,7 +133,7 @@ function buildScheduleDialog (json) {
$("#schedule_calendar").fullCalendar( 'refetchEvents' );
}}
});
//set the start end times so the builder datatables knows its time range.
fnServer.start = json.start;
fnServer.end = json.end;
@ -124,7 +141,17 @@ function buildScheduleDialog (json) {
AIRTIME.library.libraryInit();
AIRTIME.showbuilder.builderDataTable();
dialog.find(".dataTables_scrolling")
.css("max-height", height - 110 - 155);
dialog.dialog('open');
//calculate dynamically width for the library search input.
libLength = dialog.find("#library_display_length");
libType = dialog.find("#library_display_type");
libFilter = dialog.find("#library_display_filter");
libFilter.find("input").width(libFilter.width() - libType.width() - libLength.width() - 80);
}
function buildContentDialog (json){

View file

@ -14,6 +14,34 @@ var AIRTIME = (function(AIRTIME){
}
}
mod.timeout = undefined;
mod.resetTimestamp = function() {
var timestamp = $("#sb_timestamp");
//reset timestamp value since input values could have changed.
timestamp.val(-1);
};
mod.setTimestamp = function(timestamp) {
$("#sb_timestamp").val(timestamp);
};
mod.getTimestamp = function() {
var timestamp = $("#sb_timestamp"),
val;
//if the timestamp field is on the page return it, or give the default of -1
//to ensure a page refresh.
if (timestamp.length === 1) {
val = timestamp.val();
}
else {
val = -1;
}
return val;
};
mod.fnAdd = function(aMediaIds, aSchedIds) {
var oLibTT = TableTools.fnGetInstance('library_display');
@ -47,6 +75,8 @@ var AIRTIME = (function(AIRTIME){
};
fnServerData = function ( sSource, aoData, fnCallback ) {
aoData.push( { name: "timestamp", value: AIRTIME.showbuilder.getTimestamp()} );
aoData.push( { name: "format", value: "json"} );
if (fnServerData.hasOwnProperty("start")) {
@ -65,7 +95,10 @@ var AIRTIME = (function(AIRTIME){
"type": "GET",
"url": sSource,
"data": aoData,
"success": fnCallback
"success": function(json) {
AIRTIME.showbuilder.setTimestamp(json.timestamp);
fnCallback(json);
}
} );
};
@ -74,7 +107,8 @@ var AIRTIME = (function(AIRTIME){
mod.builderDataTable = function() {
var tableDiv = $('#show_builder_table'),
oTable,
fnRemoveSelectedItems;
fnRemoveSelectedItems,
tableHeight;
fnRemoveSelectedItems = function() {
var oTT = TableTools.fnGetInstance('show_builder_table'),
@ -269,7 +303,11 @@ var AIRTIME = (function(AIRTIME){
markerDiv,
td,
$lib = $("#library_content"),
tr;
tr,
oTable = $('#show_builder_table').dataTable(),
aData;
clearTimeout(AIRTIME.showbuilder.timeout);
//only create the cursor arrows if the library is on the page.
if ($lib.length > 0 && $lib.filter(":visible").length > 0) {
@ -297,21 +335,37 @@ var AIRTIME = (function(AIRTIME){
//if the now playing song is visible set a timeout to redraw the table at the start of the next song.
tr = tableDiv.find("tr.sb-now-playing");
if (tr.length > 0) {
var oTable = $('#show_builder_table').dataTable(),
aData = tr.data("aData");
aData = tr.data("aData");
setTimeout(function(){
AIRTIME.showbuilder.resetTimestamp();
oTable.fnDraw();
}, aData.refresh * 1000); //need refresh in milliseconds
}
//current song is not set, set a timeout to refresh when the first item on the timeline starts.
else {
tr = tableDiv.find("tbody tr.sb-allowed.sb-header:first");
if (tr.length > 0) {
aData = tr.data("aData");
AIRTIME.showbuilder.timeout = setTimeout(function(){
AIRTIME.showbuilder.resetTimestamp();
oTable.fnDraw();
}, aData.timeUntil * 1000); //need refresh in milliseconds
}
}
},
"fnHeaderCallback": function(nHead) {
$(nHead).find("input[type=checkbox]").attr("checked", false);
},
//remove any selected nodes before the draw.
"fnPreDrawCallback": function( oSettings ) {
var oTT = TableTools.fnGetInstance('show_builder_table');
var oTT;
oTT = TableTools.fnGetInstance('show_builder_table');
oTT.fnSelectNone();
},
@ -371,7 +425,7 @@ var AIRTIME = (function(AIRTIME){
},
// R = ColReorderResize, C = ColVis, T = TableTools
"sDom": 'Rr<"H"CT>t<"F">',
"sDom": 'Rr<"H"CT>t',
"sAjaxDataProp": "schedule",
"sAjaxSource": "/showbuilder/builder-feed"

View file

@ -1,8 +1,24 @@
$(document).ready(function(){
var oBaseDatePickerSettings,
var viewport = AIRTIME.utilities.findViewportDimensions(),
lib = $("#library_content"),
builder = $("#show_builder"),
widgetHeight = viewport.height - 185,
screenWidth = Math.floor(viewport.width - 110),
oBaseDatePickerSettings,
oBaseTimePickerSettings,
oRange;
oRange,
dateStartId = "#sb_date_start",
timeStartId = "#sb_time_start",
dateEndId = "#sb_date_end",
timeEndId = "#sb_time_end";
//set the heights of the main widgets.
lib.height(widgetHeight);
//builder takes all the screen on first load
builder.height(widgetHeight)
.width(screenWidth);
oBaseDatePickerSettings = {
dateFormat: 'yy-mm-dd',
@ -18,78 +34,10 @@ $(document).ready(function(){
defaultTime: '0:00'
};
/*
* Get the schedule range start in unix timestamp form (in seconds).
* defaults to NOW if nothing is selected.
*
* @param String sDatePickerId
*
* @param String sTimePickerId
*
* @return Number iTime
*/
function fnGetTimestamp(sDatePickerId, sTimePickerId) {
var date,
time,
iTime,
iServerOffset,
iClientOffset;
if ($(sDatePickerId).val() === "") {
return 0;
}
date = $(sDatePickerId).val();
time = $(sTimePickerId).val();
date = date.split("-");
time = time.split(":");
//0 based month in js.
oDate = new Date(date[0], date[1]-1, date[2], time[0], time[1]);
iTime = oDate.getTime(); //value is in millisec.
iTime = Math.round(iTime / 1000);
iServerOffset = serverTimezoneOffset;
iClientOffset = oDate.getTimezoneOffset() * -60;//function returns minutes
//adjust for the fact the the Date object is in client time.
iTime = iTime + iClientOffset + iServerOffset;
return iTime;
}
/*
* Returns an object containing a unix timestamp in seconds for the start/end range
*
* @return Object {"start", "end", "range"}
*/
function fnGetScheduleRange() {
var iStart,
iEnd,
iRange,
DEFAULT_RANGE = 60*60*24;
iStart = fnGetTimestamp("#sb_date_start", "#sb_time_start");
iEnd = fnGetTimestamp("#sb_date_end", "#sb_time_end");
iRange = iEnd - iStart;
if (iRange === 0 || iEnd < iStart) {
iEnd = iStart + DEFAULT_RANGE;
iRange = DEFAULT_RANGE;
}
return {
start: iStart,
end: iEnd,
range: iRange
};
}
$("#sb_date_start").datepicker(oBaseDatePickerSettings);
$("#sb_time_start").timepicker(oBaseTimePickerSettings);
$("#sb_date_end").datepicker(oBaseDatePickerSettings);
$("#sb_time_end").timepicker(oBaseTimePickerSettings);
builder.find(dateStartId).datepicker(oBaseDatePickerSettings);
builder.find(timeStartId).timepicker(oBaseTimePickerSettings);
builder.find(dateEndId).datepicker(oBaseDatePickerSettings);
builder.find(timeEndId).timepicker(oBaseTimePickerSettings);
$("#sb_submit").click(function(ev){
var fn,
@ -97,7 +45,10 @@ $(document).ready(function(){
op,
oTable = $('#show_builder_table').dataTable();
oRange = fnGetScheduleRange();
//reset timestamp value since input values could have changed.
AIRTIME.showbuilder.resetTimestamp();
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId, dateEndId, timeEndId);
fn = oTable.fnSettings().fnServerData;
fn.start = oRange.start;
@ -120,40 +71,70 @@ $(document).ready(function(){
var $button = $(this),
$lib = $("#library_content"),
$builder = $("#show_builder"),
oTable = $("#show_builder_table").dataTable();
schedTable = $("#show_builder_table").dataTable();
if ($button.hasClass("sb-edit")) {
//reset timestamp to redraw the cursors.
AIRTIME.showbuilder.resetTimestamp();
$lib.show();
$lib.width("45%");
$builder.width("50%");
$lib.width(Math.floor(screenWidth * 0.5));
$builder.width(Math.floor(screenWidth * 0.5));
$button.removeClass("sb-edit");
$button.addClass("sb-finish-edit");
$button.val("Close Library");
}
else if($button.hasClass("sb-finish-edit")) {
else if ($button.hasClass("sb-finish-edit")) {
$lib.hide();
$builder.width("95%");
$builder.width(screenWidth);
$button.removeClass("sb-finish-edit");
$button.addClass("sb-edit");
$button.val("Add Files");
}
oTable.fnDraw();
schedTable.fnDraw();
});
oRange = fnGetScheduleRange();
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId, dateEndId, timeEndId);
AIRTIME.showbuilder.fnServerData.start = oRange.start;
AIRTIME.showbuilder.fnServerData.end = oRange.end;
AIRTIME.library.libraryInit();
AIRTIME.showbuilder.builderDataTable();
//check if the timeline viewed needs updating.
setInterval(function(){
var oTable = $('#show_builder_table').dataTable();
oTable.fnDraw();
}, 20 * 1000); //need refresh in milliseconds
var data = {},
oTable = $('#show_builder_table').dataTable(),
fn = oTable.fnSettings().fnServerData,
start = fn.start,
end = fn.end;
data["format"] = "json";
data["start"] = start;
data["end"] = end;
data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
if (fn.hasOwnProperty("ops")) {
data["myShows"] = fn.ops.myShows;
data["showFilter"] = fn.ops.showFilter;
}
$.ajax( {
"dataType": "json",
"type": "GET",
"url": "/showbuilder/check-builder-feed",
"data": data,
"success": function(json) {
if (json.update === true) {
oTable.fnDraw();
}
}
} );
}, 5 * 1000); //need refresh in milliseconds
});

View file

@ -0,0 +1,113 @@
var AIRTIME = (function(AIRTIME){
var mod;
if (AIRTIME.utilities === undefined) {
AIRTIME.utilities = {};
}
mod = AIRTIME.utilities;
mod.findViewportDimensions = function() {
var viewportwidth,
viewportheight;
// the more standards compliant browsers (mozilla/netscape/opera/IE7) use
// window.innerWidth and window.innerHeight
if (typeof window.innerWidth != 'undefined') {
viewportwidth = window.innerWidth, viewportheight = window.innerHeight;
}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first
// line in the document)
else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth != 'undefined'
&& document.documentElement.clientWidth != 0) {
viewportwidth = document.documentElement.clientWidth;
viewportheight = document.documentElement.clientHeight;
}
// older versions of IE
else {
viewportwidth = document.getElementsByTagName('body')[0].clientWidth;
viewportheight = document.getElementsByTagName('body')[0].clientHeight;
}
return {
width: viewportwidth,
height: viewportheight
};
};
/*
* Get the schedule range start in unix timestamp form (in seconds).
* defaults to NOW if nothing is selected.
*
* @param String sDatePickerId
*
* @param String sTimePickerId
*
* @return Number iTime
*/
mod.fnGetTimestamp = function(sDateId, sTimeId) {
var date,
time,
iTime,
iServerOffset,
iClientOffset,
temp;
temp = $(sDateId).val();
if ( temp === "") {
return 0;
}
else {
date = temp;
}
time = $(sTimeId).val();
date = date.split("-");
time = time.split(":");
//0 based month in js.
oDate = new Date(date[0], date[1]-1, date[2], time[0], time[1]);
iTime = oDate.getTime(); //value is in millisec.
iTime = Math.round(iTime / 1000);
iServerOffset = serverTimezoneOffset;
iClientOffset = oDate.getTimezoneOffset() * -60;//function returns minutes
//adjust for the fact the the Date object is in client time.
iTime = iTime + iClientOffset + iServerOffset;
return iTime;
};
/*
* Returns an object containing a unix timestamp in seconds for the start/end range
*
* @return Object {"start", "end", "range"}
*/
mod.fnGetScheduleRange = function(dateStart, timeStart, dateEnd, timeEnd) {
var iStart,
iEnd,
iRange,
DEFAULT_RANGE = 60*60*24;
iStart = AIRTIME.utilities.fnGetTimestamp(dateStart, timeStart);
iEnd = AIRTIME.utilities.fnGetTimestamp(dateEnd, timeEnd);
iRange = iEnd - iStart;
if (iRange === 0 || iEnd < iStart) {
iEnd = iStart + DEFAULT_RANGE;
iRange = DEFAULT_RANGE;
}
return {
start: iStart,
end: iEnd,
range: iRange
};
};
return AIRTIME;
}(AIRTIME || {}));