//-------------------------------------------------------------------------------------------------------------------------------- // 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 += "
  • " + "" + ele.track_title + " - " + "" + ele.creator + "" + "" + ele.length + "" + "
  • "; } }); } else { for (var key in data.crit) { $.each(data.crit[key], function (index, ele) { var extra = ele["extra"] == null ? "" : "- " + ele["extra"]; $html += "
  • " + "" + ele["display_name"] + "" + "" + ele["display_modifier"] + "" + "" + ele["value"] + "" + "" + extra + "" + "
  • "; }); } $html += "

  • " + $.i18n._("Limit to: ") + data.limit.value + " " + data.limit.display_modifier + "
  • "; } $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 $('
  • ')[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) or in the waveform editor if ($(event.target).is("form 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);