sintonia/legacy/public/js/airtime/library/spl.js

1704 lines
46 KiB
JavaScript

//--------------------------------------------------------------------------------------------------------------------------------
// Playlist Functions
//--------------------------------------------------------------------------------------------------------------------------------
var AIRTIME = (function (AIRTIME) {
if (AIRTIME.playlist === undefined) {
AIRTIME.playlist = {};
}
var mod = AIRTIME.playlist,
viewport,
$lib,
$pl,
widgetHeight;
function isTimeValid(time) {
//var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$");
var regExpr = new RegExp(
"^\\d{2}[:]([0-5]){1}([0-9]){1}[:]([0-5]){1}([0-9]){1}([.]\\d{1})?$",
);
return regExpr.test(time);
}
function isFadeValid(fade) {
var regExpr = new RegExp("^[0-9]+(\\.\\d+)?$");
return regExpr.test(fade);
}
function playlistError(json) {
alert(json.error);
}
function stopAudioPreview() {
// stop any preview playing
$("#jquery_jplayer_1").jPlayer("stop");
}
function highlightActive(el) {
$(el).addClass("ui-state-active");
}
function unHighlightActive(el) {
$(el).removeClass("ui-state-active");
}
function showError(el, error) {
$(el).parent().next().empty().append(error).show();
}
function hideError(el) {
$(el).parent().next().empty().hide();
}
function changeCueIn(event) {
event.stopPropagation();
var span = $(this),
id = span.parent().attr("id").split("_").pop(),
url = baseUrl + "playlist/set-cue",
cueIn = $.trim(span.text()),
li = span.parents("li"),
unqid = li.attr("unqid"),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isTimeValid(cueIn)) {
showError(span, $.i18n._("please put in a time '00:00:00 (.0)'"));
return;
}
$.post(
url,
{ format: "json", cueIn: cueIn, id: id, modified: lastMod, type: type },
function (json) {
if (json.error !== undefined) {
playlistError(json);
return;
}
if (json.cue_error !== undefined) {
showError(span, json.cue_error);
return;
}
setPlaylistContent(json);
li = $(".side_playlist.active-tab li[unqid=" + unqid + "]");
li.find(".cue-edit").toggle();
highlightActive(li);
highlightActive(li.find(".spl_cue"));
},
);
}
function changeCueOut(event) {
event.stopPropagation();
var span = $(this),
id = span.parent().attr("id").split("_").pop(),
url = baseUrl + "playlist/set-cue",
cueOut = $.trim(span.text()),
li = span.parents("li"),
unqid = li.attr("unqid"),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isTimeValid(cueOut)) {
showError(span, $.i18n._("please put in a time '00:00:00 (.0)'"));
return;
}
$.post(
url,
{ format: "json", cueOut: cueOut, id: id, modified: lastMod, type: type },
function (json) {
if (json.error !== undefined) {
playlistError(json);
return;
}
if (json.cue_error !== undefined) {
showError(span, json.cue_error);
return;
}
setPlaylistContent(json);
li = $(".side_playlist.active-tab li[unqid=" + unqid + "]");
li.find(".cue-edit").toggle();
highlightActive(li);
highlightActive(li.find(".spl_cue"));
},
);
}
/* used from waveform pop-up */
function changeCues($el, id, cueIn, cueOut) {
var url = baseUrl + "playlist/set-cue",
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val(),
li,
span;
if (!isTimeValid(cueIn)) {
$el
.find(".cue-in-error")
.val($.i18n._("please put in a time '00:00:00 (.0)'"))
.show();
return;
} else {
$el.find(".cue-in-error").hide();
}
if (!isTimeValid(cueOut)) {
$el
.find(".cue-out-error")
.val($.i18n._("please put in a time '00:00:00 (.0)'"))
.show();
return;
} else {
$el.find(".cue-out-error").hide();
}
$.post(
url,
{
format: "json",
cueIn: cueIn,
cueOut: cueOut,
id: id,
modified: lastMod,
type: type,
},
function (json) {
$el.dialog("destroy");
$el.remove();
if (json.error !== undefined) {
playlistError(json);
return;
}
if (json.cue_error !== undefined) {
li = $(".side_playlist.active-tab li[unqid=" + id + "]");
if (json.code === 0) {
span = $("#spl_cue_in_" + id).find("span");
showError(span, json.cue_error);
span = $("#spl_cue_out_" + id).find("span");
showError(span, json.cue_error);
} else if (json.code === 1) {
span = $("#spl_cue_in_" + id).find("span");
showError(span, json.cue_error);
} else if (json.code === 2) {
span = $("#spl_cue_out_" + id).find("span");
showError(span, json.cue_error);
}
return;
}
setPlaylistContent(json);
li = $(".side_playlist.active-tab li[unqid=" + id + "]");
li.find(".cue-edit").toggle();
highlightActive(li);
highlightActive(li.find(".spl_cue"));
},
);
}
/* used from waveform pop-up */
function changeCrossfade($el, id1, id2, fadeIn, fadeOut, offset, id) {
var url = baseUrl + "playlist/set-crossfade",
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
$.post(
url,
{
format: "json",
fadeIn: fadeIn,
fadeOut: fadeOut,
id1: id1,
id2: id2,
offset: offset,
modified: lastMod,
type: type,
},
function (json) {
$el.dialog("destroy");
$el.remove();
if (json.error !== undefined) {
playlistError(json);
return;
}
setPlaylistContent(json);
$li = $pl.find("li[unqid=" + id + "]");
$li.find(".crossfade").toggle();
highlightActive($li.find(".spl_fade_control"));
},
);
}
function changeFadeIn(event) {
event.preventDefault();
var span = $(this),
id = span.parent().attr("id").split("_").pop(),
url = baseUrl + "playlist/set-fade",
fadeIn = $.trim(span.text()),
li = span.parents("li"),
unqid = li.attr("unqid"),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isFadeValid(fadeIn)) {
showError(
span,
$.i18n._("Please enter a valid time in seconds. Eg. 0.5"),
);
return;
} else {
hideError(span);
}
$.post(
url,
{ format: "json", fadeIn: fadeIn, id: id, modified: lastMod, type: type },
function (json) {
if (json.error !== undefined) {
playlistError(json);
return;
}
if (json.fade_error !== undefined) {
showError(span, json.fade_error);
return;
}
setPlaylistContent(json);
li = $pl.find("li[unqid=" + unqid + "]");
li.find(".crossfade").toggle();
highlightActive(li.find(".spl_fade_control"));
},
);
}
function changeFadeOut(event) {
event.stopPropagation();
var span = $(this),
id = span.parent().attr("id").split("_").pop(),
url = baseUrl + "playlist/set-fade",
fadeOut = $.trim(span.text()),
li = span.parents("li"),
unqid = li.attr("unqid"),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isFadeValid(fadeOut)) {
showError(
span,
$.i18n._("Please enter a valid time in seconds. Eg. 0.5"),
);
return;
} else {
hideError(span);
}
$.post(
url,
{
format: "json",
fadeOut: fadeOut,
id: id,
modified: lastMod,
type: type,
},
function (json) {
if (json.error !== undefined) {
playlistError(json);
return;
}
if (json.fade_error !== undefined) {
showError(span, json.fade_error);
return;
}
setPlaylistContent(json);
li = $pl.find("li[unqid=" + unqid + "]");
li.find(".crossfade").toggle();
highlightActive(li.find(".spl_fade_control"));
},
);
}
function submitOnEnter(event) {
//enter was pressed
if (event.keyCode === 13) {
event.preventDefault();
$(this).blur();
}
}
function openFadeEditor(event) {
var li;
event.stopPropagation();
li = $(this).parents("li");
li.find(".crossfade").toggle();
if ($(this).hasClass("ui-state-active")) {
unHighlightActive(this);
} else {
highlightActive(this);
}
}
function openCueEditor(event) {
var li, icon;
event.stopPropagation();
icon = $(this);
li = $(this).parents("li");
li.find(".cue-edit").toggle();
if (li.hasClass("ui-state-active")) {
unHighlightActive(li);
unHighlightActive(icon);
} else {
highlightActive(li);
highlightActive(icon);
}
}
function redrawLib() {
var dt = $lib.find("#library_display").dataTable();
dt.fnStandingRedraw();
AIRTIME.library.redrawChosen();
}
function setPlaylistContent(json) {
var $html = $(json.html);
$("#spl_name > a").empty().append(json.name);
$pl.find(".obj_length").empty().append(json.length);
$("#fieldset-metadate_change textarea").empty().val(json.description);
$pl.find(".spl_sortable").off("focusout keydown");
$pl.find(".spl_sortable").empty().append($html);
setCueEvents();
setFadeEvents();
mod.setModified(json.modified);
AIRTIME.tabs.getActiveTab().setName(json.name);
AIRTIME.playlist.validatePlaylistElements();
redrawLib();
}
mod.setFadeIcon = function () {
var contents = $pl.find(".spl_sortable");
var show = contents.is(":visible");
var empty = $pl.find(".spl_empty");
if (!show || empty.length > 0) {
$pl.find("#spl_crossfade").attr("disabled", "disabled");
} else {
//get list of playlist contents
var list = contents.children();
//if first and last items are blocks, hide the fade icon
var first = list.first();
var last = list.last();
if (
first.find(":first-child").children().attr("blockid") !== undefined &&
last.find(":first-child").children().attr("blockid") !== undefined
) {
$pl.find("#spl_crossfade").attr("disabled", "disabled");
} else {
$pl.find("#spl_crossfade").removeAttr("disabled");
}
}
$(".zend_form + .spl-no-margin > div:has(*:visible):last").css(
"margin-left",
0,
);
};
mod.getId = function (pl) {
pl = pl === undefined ? $pl : pl;
return parseInt(pl.find(".obj_id").val(), 10);
};
mod.getModified = function (pl) {
pl = pl === undefined ? $pl : pl;
return parseInt(pl.find(".obj_lastMod").val(), 10);
};
mod.setModified = function (modified) {
$pl.find(".obj_lastMod").val(modified);
};
function setTitleLabel(title) {
$pl.find(".title_obj_name").text(title);
}
function openPlaylistPanel() {
viewport = AIRTIME.utilities.findViewportDimensions();
var screenWidth = Math.floor(viewport.width - 40);
widgetHeight = viewport.height - 185;
$pl.show().width(Math.floor(screenWidth * 0.44));
$pl.height(widgetHeight);
$("#pl_edit").hide();
}
//Purpose of this function is to iterate over all playlist elements
//and verify whether they can be previewed by the browser or not. If not
//then the playlist element is greyed out
mod.validatePlaylistElements = function () {
$.each($("div .big_play"), function (index, value) {
if ($(value).attr("blockId") === undefined) {
var mime = $(value).attr("data-mime-type");
//If mime is undefined it is likely because the file was
//deleted from the library. This case is handled in mod.onReady()
if (mime !== undefined) {
if (isAudioSupported(mime)) {
$(value).bind("click", openAudioPreview);
} else {
$(value).attr("class", "big_play_disabled dark_class");
$(value).qtip({
content:
$.i18n._(
"Your browser does not support playing this file type: ",
) + mime,
show: "mouseover",
hide: {
delay: 500,
fixed: true,
},
style: {
border: {
width: 0,
radius: 4,
},
classes: "ui-tooltip-dark ui-tooltip-rounded",
},
position: {
my: "left bottom",
at: "right center",
},
});
}
}
} else {
if ($(value).attr("blocktype") === "dynamic") {
$(value).attr("class", "big_play_disabled dark_class");
$(value).qtip({
content: $.i18n._("Dynamic block is not previewable"),
show: "mouseover",
hide: {
delay: 500,
fixed: true,
},
style: {
border: {
width: 0,
radius: 4,
},
classes: "ui-tooltip-dark ui-tooltip-rounded",
},
position: {
my: "left bottom",
at: "right center",
},
});
} else {
$(value).bind("click", openAudioPreview);
}
}
});
};
//sets events dynamically for playlist entries (each row in the playlist)
function setPlaylistEntryEvents() {
$pl.delegate(".spl_sortable .ui-icon-closethick", {
click: function (ev) {
var id;
id = parseInt($(this).attr("id").split("_").pop(), 10);
AIRTIME.playlist.fnDeleteItems([id]);
},
});
$pl.delegate(".spl_fade_control", { click: openFadeEditor });
$pl.delegate(".spl_cue", { click: openCueEditor });
$pl.delegate(".spl_block_expand", {
click: function (ev) {
var id = parseInt($(this).attr("id").split("_").pop(), 10);
var blockId = parseInt($(this).attr("blockId"), 10);
if ($(this).hasClass("close")) {
var sUrl = baseUrl + "playlist/get-block-info";
mod.disableUI();
$.post(sUrl, { format: "json", id: blockId }, function (data) {
$html = "";
var isStatic = data.isStatic;
delete data.type;
if (isStatic) {
$.each(data, function (index, ele) {
if (ele.track_title !== undefined) {
if (ele.creator === null) {
ele.creator = "";
}
if (ele.track_title === null) {
ele.track_title = "";
}
$html +=
"<li>" +
"<span class='block-item-title'>" +
ele.track_title +
" - </span>" +
"<span class='block-item-author'>" +
ele.creator +
"</span>" +
"<span class='block-item-time'>" +
ele.length +
"</span>" +
"</li>";
}
});
} else {
for (var key in data.crit) {
$.each(data.crit[key], function (index, ele) {
var extra = ele["extra"] == null ? "" : "- " + ele["extra"];
$html +=
"<li>" +
"<span class='block-item-title'>" +
ele["display_name"] +
"</span>" +
"<span class='block-item-criteria'>" +
ele["display_modifier"] +
"</span>" +
"<span class='block-item-criteria'>" +
ele["value"] +
"</span>" +
"<span class='block-item-criteria'>" +
extra +
"</span>" +
"</li>";
});
}
$html +=
"<li><br /><span class='block-item-title'>" +
$.i18n._("Limit to: ") +
data.limit.value +
" " +
data.limit.display_modifier +
"</span></li>";
}
$pl
.find("#block_" + id + "_info")
.html($html)
.show();
mod.enableUI();
});
$(this).removeClass("close");
} else {
$pl
.find("#block_" + id + "_info")
.html("")
.hide();
$(this).addClass("close");
}
},
});
}
//sets events dynamically for the cue editor.
function setCueEvents() {
var temp = $(".active-tab .spl_sortable");
temp.on("focusout", ".spl_cue_in span", changeCueIn);
temp.on("keydown", ".spl_cue_in span", submitOnEnter);
temp.on("focusout", ".spl_cue_out span", changeCueOut);
temp.on("keydown", ".spl_cue_out span", submitOnEnter);
//remove show waveform buttons since web audio api is not supported.
if (!(window.AudioContext || window.webkitAudioContext)) {
temp
.find(".pl-waveform-cues-btn")
.parent()
.html(
$.i18n._(
"Waveform features are available in a browser supporting the Web Audio API",
),
);
}
}
//sets events dynamically for the fade editor.
function setFadeEvents() {
var temp = $(".active-tab .spl_sortable");
temp.on("focusout", ".spl_fade_in span", changeFadeIn);
temp.on("keydown", ".spl_fade_in span", submitOnEnter);
temp.on("focusout", ".spl_fade_out span", changeFadeOut);
temp.on("keydown", ".spl_fade_out span", submitOnEnter);
//remove show waveform buttons since web audio api is not supported.
if (!(window.AudioContext || window.webkitAudioContext)) {
temp
.find(".pl-waveform-fades-btn")
.parent()
.html(
$.i18n._(
"Waveform features are available in a browser supporting the Web Audio API",
),
);
}
}
function initialEvents() {
var cachedDescription;
//main playlist fades events
$pl.on("click", "#spl_crossfade", function () {
var lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if ($(this).hasClass("ui-state-active")) {
$(this).removeClass("ui-state-active");
$pl.find("#crossfade_main").hide();
} else {
$(this).addClass("ui-state-active");
var url = baseUrl + "playlist/get-playlist-fades";
$.post(
url,
{ format: "json", modified: lastMod, type: type },
function (json) {
if (json.error !== undefined) {
playlistError(json);
} else {
var fadeIn = $pl.find("input.spl_main_fade_in");
var fadeOut = $pl.find("input.spl_main_fade_out");
if (json.fadeIn == null) {
fadeIn.parent().prev().hide();
fadeIn.hide();
} else {
fadeIn.parent().prev().show();
fadeIn.show();
fadeIn.val(json.fadeIn);
fadeIn.text(json.fadeIn);
}
if (json.fadeOut == null) {
fadeOut.parent().prev().hide();
fadeOut.hide();
} else {
fadeOut.parent().prev().show();
fadeOut.show();
fadeOut.val(json.fadeOut);
fadeOut.text(json.fadeOut);
}
if (json.fadeIn != null || json.fadeOut != null) {
$pl.find("#crossfade_main").show();
}
}
},
);
}
});
$pl.on("blur", "input.spl_main_fade_in", function (event) {
event.stopPropagation();
var url = baseUrl + "playlist/set-playlist-fades",
input = $(this),
fadeIn = $.trim(input.val()),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isFadeValid(fadeIn)) {
showError(
input,
$.i18n._("Please enter a valid time in seconds. Eg. 0.5"),
);
return;
} else {
hideError(input);
}
$.post(
url,
{ format: "json", fadeIn: fadeIn, modified: lastMod, type: type },
function (json) {
hideError(input);
if (json.modified !== undefined) {
mod.setModified(json.modified);
}
},
);
});
$pl.on("blur", "input.spl_main_fade_out", function (event) {
event.stopPropagation();
var url = baseUrl + "playlist/set-playlist-fades",
input = $(this),
fadeOut = $.trim(input.val()),
lastMod = mod.getModified(),
type = $pl.find(".obj_type").val();
if (!isFadeValid(fadeOut)) {
showError(
input,
$.i18n._("Please enter a valid time in seconds. Eg. 0.5"),
);
return;
} else {
hideError(input);
}
$.post(
url,
{ format: "json", fadeOut: fadeOut, modified: lastMod, type: type },
function (json) {
hideError(input);
if (json.modified !== undefined) {
mod.setModified(json.modified);
}
},
);
});
$pl.on(
"keydown",
"span.spl_main_fade_in, span.spl_main_fade_out",
submitOnEnter,
);
$pl.on("click", "#crossfade_main > .ui-icon-closethick", function () {
$pl.find("#spl_crossfade").removeClass("ui-state-active");
$pl.find("#crossfade_main").hide();
});
//end main playlist fades.
//edit playlist name event
$pl.on("keydown", ".playlist_name_display", submitOnEnter);
//$pl.on("blur", ".playlist_name_display", editName);
//edit playlist description events
$pl.on("click", "legend", function () {
var $fs = $(this).parents("fieldset");
if ($fs.hasClass("closed")) {
cachedDescription = $fs.find("textarea").val();
$fs.removeClass("closed");
} else {
$fs.addClass("closed");
}
});
$pl.on("click", 'button[id="playlist_shuffle_button"]', function () {
obj_id = $pl.find(".obj_id").val();
url = baseUrl + "playlist/shuffle";
enableLoadingIcon();
$.post(url, { format: "json", obj_id: obj_id }, function (json) {
if (json.error !== undefined) {
alert(json.error);
} else {
if (json.result == "0") {
$pl.find(".success").text($.i18n._("Playlist shuffled"));
$pl.find(".success").show();
mod.playlistResponse(json);
}
}
disableLoadingIcon();
setTimeout(removeSuccessMsg, 5000);
});
});
$pl.find("#webstream_save").on("click", function () {
//get all fields and POST to server
//description
//stream url
//default_length
//playlist name
var id = $pl.find(".obj_id").attr("value");
var description = $pl.find("#description").val();
var streamurl = $pl.find("#streamurl-element input").val();
var length = $pl.find("#streamlength-element input").val();
var name = $pl.find(".playlist_name_display").val();
//hide any previous errors (if any)
$(".side_playlist.active-tab .errors").empty().hide();
var url = baseUrl + "webstream/save";
$.post(
url,
{
format: "json",
id: id,
description: description,
url: streamurl,
length: length,
name: name,
},
function (json) {
if (json.analysis) {
for (var s in json.analysis) {
var field = json.analysis[s];
if (!field[0]) {
var elemId = "#" + s + "-error";
var $div = $(".side_playlist.active-tab " + elemId)
.text(field[1])
.show();
}
}
} else {
var $status = $(".side_playlist.active-tab .status");
$status.html(json.statusMessage);
$status.show();
setTimeout(function () {
$status.fadeOut("slow", function () {
$status.empty();
});
}, 5000);
$pl.find(".title_obj_name").val(name);
AIRTIME.tabs.getActiveTab().setName(json.name).close();
var $ws_id = $(".active-tab .obj_id");
$ws_id.attr("value", json.streamId);
var $ws_id = $("#ws_delete");
$ws_id.show();
var length = $(".side_playlist.active-tab .ws_length");
length.text(json.length);
//redraw the library to show the new webstream
redrawLib();
}
},
);
});
$pl.find("#webstream_cancel, #cancel_button").on("click", function () {
var tabId = $pl.attr("data-tab-id");
$("li[data-tab-id=" + tabId + "] .lib_pl_close").click();
});
$lib.on("click", "#pl_edit", function () {
openPlaylistPanel();
$.ajax({
url: baseUrl + "usersettings/set-library-screen-settings",
type: "POST",
data: {
settings: {
playlist: true,
},
format: "json",
},
dataType: "json",
});
});
// Unbind so each tab is only handled by its own close button
$(".lib_pl_close")
.unbind()
.click(function (e) {
e.preventDefault();
e.stopPropagation();
$(this).unbind("click"); // Prevent repeated clicks in quick succession from closing multiple tabs
var tabId = $(this).closest("li").attr("data-tab-id"),
tab = AIRTIME.tabs.get(tabId);
// We need to update the text on the add button
AIRTIME.library.checkAddButton();
// We also need to run the draw callback to update how dragged items are drawn
AIRTIME.library.fnDrawCallback();
var playlistNameElem = tab.tab.find(".tab-name");
var name = playlistNameElem.text().trim();
// TODO: refactor - this code is pretty finicky...
if (
(name == $.i18n._("Untitled Playlist") ||
name == $.i18n._("Untitled Smart Block")) &&
tab.contents.find(".spl_sortable .spl_empty").length == 1
) {
mod.fnDelete(undefined, tab);
}
tab.close();
// save settings if we are not closing the "Scheduled Shows" tab
if (tabId != "0") {
$.ajax({
url: baseUrl + "usersettings/set-library-screen-settings",
type: "POST",
data: {
settings: {
playlist: false,
},
format: "json",
},
dataType: "json",
});
}
});
$pl
.find("#save_button")
.unbind()
.on("click", function (event) {
/* Smart blocks: get name, description, and criteria
* Playlists: get name, description
*/
var criteria = $pl.find("form").serializeArray(),
block_name = $pl.find(".playlist_name_display").val(),
block_desc = $pl.find('textarea[name="description"]').val(),
save_action = baseUrl + "playlist/save",
obj_id = $pl.find(".obj_id").val(),
obj_type = $pl.find(".obj_type").val(),
lastMod = mod.getModified(),
dt = $('table[id="library_display"]').dataTable();
enableLoadingIcon();
$.post(
save_action,
{
format: "json",
data: criteria,
name: block_name,
description: block_desc,
obj_id: obj_id,
type: obj_type,
modified: lastMod,
},
function (json) {
if (json.error !== undefined) {
alert(json.error);
} else {
setTitleLabel(json.name);
AIRTIME.tabs.getActiveTab().setName(json.name);
mod.setModified(json.modified);
if (obj_type == "block") {
callback(json, "save");
} else {
$pl.find(".success").text($.i18n._("Playlist saved."));
$pl.find(".success").show();
setTimeout(removeSuccessMsg, 5000);
dt.fnStandingRedraw();
}
}
mod.setFadeIcon();
disableLoadingIcon();
},
);
});
$pl
.find("#pl-bl-clear-content")
.unbind()
.on("click", function (event) {
var sUrl = baseUrl + "playlist/empty-content",
oData = {};
playlistRequest(sUrl, oData);
});
}
function setUpPlaylist() {
var sortableConf;
sortableConf = (function () {
var aReceiveItems, html, fnReceive, fnUpdate;
fnReceive = function (event, ui) {
var aItems = [],
aSelected,
i,
length;
AIRTIME.library.addToChosen(ui.item);
//filter out anything that isn't an audiofile.
aSelected = AIRTIME.library.getSelectedData();
for (i = 0, length = aSelected.length; i < length; i++) {
//console.log(aSelected[i]);
aItems.push(new Array(aSelected[i].id, aSelected[i].ftype));
}
aReceiveItems = aItems;
html = ui.helper.html();
AIRTIME.library.removeFromChosen(ui.item);
};
fnUpdate = function (event, ui) {
var prev,
aItems = [],
iAfter,
sAddType;
prev = ui.item.prev();
if (prev.hasClass("spl_empty") || prev.length === 0) {
iAfter = undefined;
sAddType = "before";
} else {
iAfter = parseInt(prev.attr("id").split("_").pop(), 10);
sAddType = "after";
}
//item was dragged in from library datatable
if (aReceiveItems !== undefined) {
$pl.find("tr.ui-draggable").after(html).empty();
aItems = aReceiveItems;
aReceiveItems = undefined;
AIRTIME.playlist.fnAddItems(aItems, iAfter, sAddType);
}
//item was reordered.
else {
aItems.push(parseInt(ui.item.attr("id").split("_").pop(), 10));
AIRTIME.playlist.fnMoveItems(aItems, iAfter);
}
};
return {
items: "li",
//hack taken from
//http://stackoverflow.com/questions/2150002/jquery-ui-sortable-how-can-i-change-the-appearance-of-the-placeholder-object
placeholder: {
element: function (currentItem) {
return $('<li class="placeholder ui-state-highlight"></li>')[0];
},
update: function (container, p) {
return;
},
},
forcePlaceholderSize: true,
//handle: 'div.list-item-container',
start: function (event, ui) {
ui.placeholder.height(56);
ui.placeholder.css("min-height", 56);
},
axis: "y",
containment: "document",
receive: fnReceive,
update: fnUpdate,
};
})();
$pl.find(".spl_sortable").sortable(sortableConf);
AIRTIME.playlist.validatePlaylistElements();
}
mod._initPlaylistTabEvents = function (newTab) {
newTab.assignTabClickHandler(function () {
if (!$(this).hasClass("active")) {
newTab.switchTo();
var type = newTab.contents.find(".obj_type").val();
if (type == "playlist" || type == "block") {
$.post(baseUrl + "playlist/edit", {
format: "json",
id: newTab.contents.find(".obj_id").val(),
type: type,
});
}
}
});
mod.init();
// functions in smart_blockbuilder.js
setupUI();
appendAddButton();
appendModAddButton();
removeButtonCheck();
mod.setFadeIcon();
};
mod._initFileMdEvents = function (newTab) {
var fileId = newTab.wrapper.find("#file_id").val();
newTab.contents.find(".md-cancel").on("click", function () {
newTab.close();
});
newTab.contents.find(".md-save").on("click", function () {
var data = newTab.wrapper.find(".edit-md-dialog form").serializeArray();
$.post(
baseUrl + "library/edit-file-md",
{ format: "json", id: fileId, data: data },
function () {
// don't redraw the library table if we are on calendar page
// we would be on calendar if viewing recorded file metadata
if ($("#schedule_calendar").length === 0) {
oTable.fnStandingRedraw();
}
},
);
newTab.close();
});
newTab.contents.find(".md-publish").on("click", function () {
AIRTIME.publish.openPublishDialog(fileId);
});
newTab.wrapper.find(".edit-md-dialog").on("keyup", function (event) {
// Don't submit if the user hits enter in a textarea (description)
if ($(event.target).is("input") && event.keyCode === 13) {
newTab.wrapper.find(".md-save").click();
}
});
mod.setupEventListeners();
};
mod.fnNew = function () {
var url = baseUrl + "playlist/new";
stopAudioPreview();
$.post(url, { format: "json", type: "playlist" }, function (json) {
var uid = AIRTIME.library.MediaTypeStringEnum.PLAYLIST + "_" + json.id;
AIRTIME.tabs.openTab(
json.html,
uid,
AIRTIME.playlist._initPlaylistTabEvents,
);
redrawLib();
});
};
mod.fnWsNew = function () {
var url = baseUrl + "webstream/new";
stopAudioPreview();
$.post(url, { format: "json" }, function (json) {
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM + "_" + json.id;
AIRTIME.tabs.openTab(
json.html,
uid,
AIRTIME.playlist._initPlaylistTabEvents,
);
redrawLib();
});
};
mod.fnNewBlock = function () {
var url = baseUrl + "playlist/new";
stopAudioPreview();
$.post(url, { format: "json", type: "block" }, function (json) {
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK + "_" + json.id;
AIRTIME.tabs.openTab(
json.html,
uid,
AIRTIME.playlist._initPlaylistTabEvents,
);
redrawLib();
});
};
mod.fileMdEdit = function (json, uid) {
AIRTIME.tabs.openTab(json.html, uid, AIRTIME.playlist._initFileMdEvents);
};
mod.fnEdit = function (data, url) {
stopAudioPreview();
$.post(
url,
{ format: "json", id: data.id, type: data.ftype },
function (json) {
AIRTIME.tabs.openTab(
json.html,
data.tr_id,
AIRTIME.playlist._initPlaylistTabEvents,
);
redrawLib();
},
);
};
mod.fnDelete = function (plid, tab) {
var url,
id,
lastMod,
type,
pl = tab.contents;
stopAudioPreview();
id = plid === undefined ? mod.getId(pl) : plid;
lastMod = mod.getModified(pl);
type = pl.find(".obj_type").val();
url = baseUrl + "playlist/delete";
$.post(
url,
{ format: "json", ids: id, modified: lastMod, type: type },
function (json) {
redrawLib();
},
);
};
mod.fnWsDelete = function (wsid) {
var url, id, lastMod;
stopAudioPreview();
id = wsid === undefined ? mod.getId() : wsid;
lastMod = mod.getModified();
type = $pl.find(".obj_type").val();
url = baseUrl + "webstream/delete";
$.post(
url,
{ format: "json", ids: id, modified: lastMod, type: type },
function (json) {
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM + "_" + id;
AIRTIME.tabs.openTab(
json.html,
uid,
AIRTIME.playlist._initPlaylistTabEvents,
);
redrawLib();
},
);
};
mod.disableUI = function () {
$lib.block({
message: "",
theme: true,
applyPlatformOpacityRules: false,
});
$pl.block({
message: "",
theme: true,
applyPlatformOpacityRules: false,
});
};
mod.enableUI = function () {
$lib.unblock();
$pl.unblock();
setupUI();
};
mod.playlistResponse = function (json) {
if (
json.error !== undefined ||
(json.result !== undefined && json.result != 0)
) {
if (json.error) {
playlistError(json);
}
AIRTIME.playlist.replaceForm(json);
AIRTIME.playlist.init();
} else {
setPlaylistContent(json);
mod.setFadeIcon();
$pl.find(".errors").hide();
}
mod.enableUI();
};
mod.replaceForm = function (json) {
$pl.find(".editor_pane_wrapper").html(json.html);
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK + "_" + json.id;
AIRTIME.tabs.openTab(
json.html,
uid,
AIRTIME.playlist._initPlaylistTabEvents,
);
};
function playlistRequest(sUrl, oData) {
var lastMod,
obj_type = $pl.find(".obj_type").val();
mod.disableUI();
lastMod = mod.getModified();
oData["modified"] = lastMod;
oData["obj_type"] = obj_type;
oData["format"] = "json";
$.post(sUrl, oData, mod.playlistResponse);
}
mod.fnAddItems = function (aItems, iAfter, sAddType) {
AIRTIME.library.selectNone();
var sUrl = baseUrl + "playlist/add-items";
oData = { aItems: aItems, afterItem: iAfter, type: sAddType };
playlistRequest(sUrl, oData);
};
mod.fnMoveItems = function (aIds, iAfter) {
var sUrl = baseUrl + "playlist/move-items",
oData = { ids: aIds, afterItem: iAfter };
playlistRequest(sUrl, oData);
};
mod.fnDeleteItems = function (aItems) {
var sUrl = baseUrl + "playlist/delete-items",
oData = { ids: aItems };
playlistRequest(sUrl, oData);
};
mod.showFadesWaveform = function (e) {
var $el = $(e.target),
$parent = $el.parents("dl"),
$li = $el.parents("li"),
$fadeOut = $parent.find(".spl_fade_out"),
$fadeIn = $parent.find(".spl_fade_in"),
$html = $($("#tmpl-pl-fades").html()),
tracks = [],
dim = AIRTIME.utilities.findViewportDimensions(),
playlistEditor,
id1,
id2,
id = $li.attr("unqid");
function removeDialog() {
playlistEditor.stop();
$html.dialog("destroy");
$html.remove();
}
if ($fadeOut.length > 0) {
tracks.push({
src: $fadeOut.data("fadeout"),
cuein: $fadeOut.data("cuein"),
cueout: $fadeOut.data("cueout"),
fades: [
{
shape: $fadeOut.data("type"),
type: "FadeOut",
end: $fadeOut.data("cueout") - $fadeOut.data("cuein"),
start:
$fadeOut.data("cueout") -
$fadeOut.data("cuein") -
$fadeOut.data("length"),
},
],
states: {
fadein: false,
shift: false,
},
});
id1 = $fadeOut.data("item");
}
if ($fadeIn.length > 0) {
tracks.push({
src: $fadeIn.data("fadein"),
start: $fadeIn.data("offset"),
cuein: $fadeIn.data("cuein"),
cueout: $fadeIn.data("cueout"),
fades: [
{
shape: $fadeIn.data("type"),
type: "FadeIn",
end: $fadeIn.data("length"),
start: 0,
},
],
states: {
fadeout: false,
shift: false,
},
});
id2 = $fadeIn.data("item");
}
//set the first track to not be moveable (might only be one track depending on what follows)
//tracks[0].states["shift"] = false;
$html.dialog({
modal: true,
title: $.i18n._("Fade Editor"),
show: "clip",
hide: "clip",
width: dim.width - 100,
height: 350,
buttons: [
{
text: $.i18n._("Cancel"),
class: "btn btn-small",
click: removeDialog,
},
{
text: $.i18n._("Save"),
class: "btn btn-small btn-inverse",
click: function () {
var json = playlistEditor.getJson(),
offset,
fadeIn,
fadeOut,
fade;
playlistEditor.stop();
if (json.length === 0) {
id1 = undefined;
id2 = undefined;
} else if (json.length === 1) {
fade = json[0]["fades"][0];
if (fade["type"] === "FadeOut") {
fadeOut = fade["end"] - fade["start"];
id2 = undefined; //incase of track decode error.
} else {
fadeIn = fade["end"] - fade["start"];
id1 = undefined; //incase of track decode error.
}
} else {
offset = json[0]["end"] - json[1]["start"];
fade = json[0]["fades"][0];
fadeOut = fade["end"] - fade["start"];
fade = json[1]["fades"][0];
fadeIn = fade["end"] - fade["start"];
}
fadeIn = fadeIn === undefined ? undefined : fadeIn.toFixed(1);
fadeOut = fadeOut === undefined ? undefined : fadeOut.toFixed(1);
changeCrossfade($html, id1, id2, fadeIn, fadeOut, offset, id);
},
},
],
open: function (event, ui) {
var config = new Config({
resolution: 15000,
state: "cursor",
mono: true,
timescale: true,
waveHeight: 80,
container: $html[0],
UITheme: "jQueryUI",
timeFormat: "hh:mm:ss.u",
});
playlistEditor = new PlaylistEditor();
playlistEditor.setConfig(config);
playlistEditor.init(tracks);
},
close: removeDialog,
resizeStop: function (event, ui) {
playlistEditor.resize();
},
});
};
mod.showCuesWaveform = function (e) {
var $el = $(e.target),
$li = $el.parents("li"),
id = $li.attr("unqid"),
$parent = $el.parent(),
uri = $parent.data("uri"),
$html = $($("#tmpl-pl-cues").html()),
cueIn = $li.find(".spl_cue_in").data("cueIn"),
cueOut = $li.find(".spl_cue_out").data("cueOut"),
cueInSec = $li.find(".spl_cue_in").data("cueSec"),
cueOutSec = $li.find(".spl_cue_out").data("cueSec"),
tracks = [
{
src: uri,
selected: {
start: cueInSec,
end: cueOutSec,
},
},
],
dim = AIRTIME.utilities.findViewportDimensions(),
playlistEditor;
function removeDialog() {
playlistEditor.stop();
$html.dialog("destroy");
$html.remove();
}
$html.find(".editor-cue-in").html(cueIn);
$html.find(".editor-cue-out").html(cueOut);
$html.on("click", ".set-cue-in", function (e) {
var cueIn = $html.find(".audio_start").val();
$html.find(".editor-cue-in").html(cueIn);
});
$html.on("click", ".set-cue-out", function (e) {
var cueOut = $html.find(".audio_end").val();
$html.find(".editor-cue-out").html(cueOut);
});
$html.dialog({
modal: true,
title: $.i18n._("Cue Editor"),
show: "clip",
hide: "clip",
width: dim.width - 100,
height: 325,
buttons: [
{
text: $.i18n._("Cancel"),
class: "btn btn-small",
click: removeDialog,
},
{
text: $.i18n._("Save"),
class: "btn btn-small btn-inverse",
click: function () {
var cueIn = $html.find(".editor-cue-in").html(),
cueOut = $html.find(".editor-cue-out").html();
playlistEditor.stop();
changeCues($html, id, cueIn, cueOut);
},
},
],
open: function (event, ui) {
var config = new Config({
resolution: 15000,
mono: true,
timescale: true,
waveHeight: 80,
container: $html[0],
UITheme: "jQueryUI",
timeFormat: "hh:mm:ss.u",
});
playlistEditor = new PlaylistEditor();
playlistEditor.setConfig(config);
playlistEditor.init(tracks);
},
close: removeDialog,
resizeStop: function (event, ui) {
playlistEditor.resize();
},
});
};
mod.setupEventListeners = function () {
initialEvents();
};
mod.setCurrent = function (pl) {
$pl = pl;
var type = $pl.find(".obj_type").val();
if (
$.inArray(type, Object.keys(AIRTIME.library.MediaTypeFullToStringEnum)) >
-1
) {
$.post(baseUrl + "playlist/change-playlist", {
id: mod.getId($pl),
type: type,
});
}
};
mod.init = function () {
if (!$pl) return;
$pl.delegate(".pl-waveform-cues-btn", {
click: function (ev) {
AIRTIME.playlist.showCuesWaveform(ev);
},
});
$pl.delegate(".pl-waveform-fades-btn", {
click: function (ev) {
AIRTIME.playlist.showFadesWaveform(ev);
},
});
setPlaylistEntryEvents();
setCueEvents();
setFadeEvents();
mod.setFadeIcon();
initialEvents();
setUpPlaylist();
$pl.find(".ui-icon-alert").qtip({
content: {
text: sprintf(
$.i18n._(
"%s is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't 'watched' anymore.",
),
PRODUCT_NAME,
),
},
position: {
adjust: {
resize: true,
method: "flip flip",
},
at: "right center",
my: "left top",
viewport: $(window),
},
style: {
classes: "ui-tooltip-dark",
},
show: "mouseover",
hide: "mouseout",
});
};
mod.onReady = function () {
$lib = $("#library_content");
$("#new-playlist").live("click", function () {
AIRTIME.playlist.fnNew();
});
$("#new-smart-block").live("click", function () {
AIRTIME.playlist.fnNewBlock();
});
$("#new-webstream").live("click", function () {
AIRTIME.playlist.fnWsNew();
});
AIRTIME.playlist.init();
};
return AIRTIME;
})(AIRTIME || {});
$(document).ready(AIRTIME.playlist.onReady);