var AIRTIME = (function (AIRTIME) { var mod, oSchedTable, SB_SELECTED_CLASS = "sb-selected", CURSOR_SELECTED_CLASS = "cursor-selected-row", NOW_PLAYING_CLASS = "sb-now-playing", $sbContent, $sbTable, $toolbar, $lib, cursors = [], cursorIds = [], showInstanceIds = [], headerFooter = [], DISABLED_CLASS = "ui-state-disabled", selectedRows, $previouslySelected, flagForDeselection; if (AIRTIME.showbuilder === undefined) { AIRTIME.showbuilder = {}; } mod = AIRTIME.showbuilder; function checkError(json) { if (json.error !== undefined) { alert(json.error); } } mod.timeout = undefined; mod.timestamp = -1; mod.showInstances = []; mod.resetTimestamp = function () { mod.timestamp = -1; }; mod.setTimestamp = function (timestamp) { mod.timestamp = timestamp; }; mod.updateCalendarStatusIcon = function (json) { //make sure we are only executing this code on the calendar view, not //the Now Playing view. if (window.location.pathname.toLowerCase().indexOf("schedule") < 0) { return; } var instance_id = json.schedule[0].instance; var lastElem = json.schedule[json.schedule.length - 1]; var $elem = $("#fc-show-instance-" + instance_id); //if the show is linked, then replace $elem to reference all linked //instances if ($elem.data("show-linked") == "1") { var show_id = $elem.data("show-id"); $elem = $('*[data-show-id="' + show_id + '"]'); } $elem.find(".show-empty, .show-partial-filled").remove(); if (json.schedule[1].empty) { $elem .find(".fc-event-inner") .append( '' ); } else if (lastElem["fRuntime"][0] == "-") { $elem .find(".fc-event-inner") .append( '' ); } }; mod.getTimestamp = function () { if (mod.timestamp !== undefined) { return mod.timestamp; } else { return -1; } }; mod.setShowInstances = function (showInstances) { mod.showInstances = showInstances; }; mod.getShowInstances = function () { return mod.showInstances; }; mod.refresh = function (schedId) { mod.resetTimestamp(); // once a track plays out we need to check if we can update // the is_scheduled flag in cc_files if (schedId > 0) { $.post( baseUrl + "schedule/update-future-is-scheduled", { format: "json", schedId: schedId }, function (data) { if (data.redrawLibTable !== undefined && data.redrawLibTable) { $("#library_content") .find("#library_display") .dataTable() .fnStandingRedraw(); } } ); oSchedTable.fnDraw(); } }; mod.checkSelectButton = function () { var $selectable = $sbTable.find("tr"); if ($selectable.length !== 0) { AIRTIME.button.enableButton("btn-group #timeline-select", false); } else { AIRTIME.button.disableButton("btn-group #timeline-select", false); } //need to check if the 'Select' button is disabled var select = $(".btn-group #timeline-select"); if (select.is(":disabled")) { select.removeAttr("disabled"); } }; mod.checkTrimButton = function () { var $over = $sbTable.find(".sb-over.sb-allowed"); if ($over.length !== 0) { AIRTIME.button.enableButton("icon-cut", true); } else { AIRTIME.button.disableButton("icon-cut", true); } }; mod.checkDeleteButton = function () { var $selected = $("." + SB_SELECTED_CLASS); var button = $("#show_builder").find(".icon-trash").parent(); if ($selected.length !== 0) { button.removeClass(DISABLED_CLASS); button.removeAttr("disabled"); } else { button.addClass(DISABLED_CLASS); button.attr("disabled", "disabled"); } }; mod.checkJumpToCurrentButton = function () { var $current = $sbTable.find("." + NOW_PLAYING_CLASS); if ($current.length !== 0) { AIRTIME.button.enableButton("icon-step-forward", true); } else { AIRTIME.button.disableButton("icon-step-forward", true); } }; mod.checkCancelButton = function () { var $current = $sbTable.find(".sb-current-show"), //this user type should be refactored into a separate users module later //when there's more time and more JS will need to know user data. userType = localStorage.getItem("user-type"), canCancel = false; if ($current.length !== 0 && $current.hasClass("sb-allowed")) { canCancel = true; } else if ( $current.length !== 0 && (userType === "A" || userType === "P") ) { canCancel = true; } if (canCancel === true) { AIRTIME.button.enableButton("icon-ban-circle", true); } else { AIRTIME.button.disableButton("icon-ban-circle", true); } }; mod.checkToolBarIcons = function () { //library may not be on the page. if (AIRTIME.library !== undefined) { AIRTIME.library.checkAddButton(); } mod.checkSelectButton(); mod.checkTrimButton(); mod.checkDeleteButton(); mod.checkJumpToCurrentButton(); mod.checkCancelButton(); }; mod.selectCursor = function ($el) { $el.addClass(CURSOR_SELECTED_CLASS); mod.checkToolBarIcons(); }; mod.removeCursor = function ($el) { $el.removeClass(CURSOR_SELECTED_CLASS); mod.checkToolBarIcons(); }; /* * sNot is an optional string to filter selected elements by. (ex removing the currently playing item) */ mod.getSelectedData = function (sNot) { var $selected = $sbTable.find("tr." + SB_SELECTED_CLASS), aData = [], i, length, $item; if (sNot !== undefined) { $selected = $selected.not("." + sNot); } for (i = 0, length = $selected.length; i < length; i++) { $item = $($selected.get(i)); aData.push($item.data("aData")); } return aData.reverse(); }; mod.selectAll = function () { var $trs = $sbTable.find("tr.lib-audio").not(".sb-past, .sb-empty"); $trs .addClass(SB_SELECTED_CLASS) .find(".sb-checkbox > input") .prop("checked", true); mod.checkToolBarIcons(); }; mod.selectNone = function () { var $trs = $sbTable.find("tr.lib-audio"); $trs .removeClass(SB_SELECTED_CLASS) .find(".sb-checkbox > input") .prop("checked", false); $previouslySelected = undefined; selectedRows = undefined; mod.checkToolBarIcons(); }; mod.disableUI = function () { $lib.block({ message: "", theme: true, applyPlatformOpacityRules: false, }); $sbContent.block({ message: "", theme: true, applyPlatformOpacityRules: false, }); }; mod.enableUI = function () { $lib.unblock(); $sbContent.unblock(); }; mod.fnItemCallback = function (json) { checkError(json); mod.getSelectedCursors(); selectedRows = $("." + SB_SELECTED_CLASS); oSchedTable.fnDraw(); mod.enableUI(); //Unneccessary reload of the library pane after moving tracks in the showbuilder pane. //$("#library_content").find("#library_display").dataTable().fnStandingRedraw(); getUsabilityHint(); }; mod.getSelectedCursors = function () { cursorIds = []; /* We need to keep record of which show the cursor belongs to * in the case where more than one show is displayed in the show builder * because header and footer rows have the same id */ showInstanceIds = []; /* Keeps track if the row is a footer. We need to do this because * header and footer rows have the save cursorIds and showInstanceId * so both will be selected in the draw callback */ headerFooter = []; cursors = $(".cursor-selected-row"); for (i = 0; i < cursors.length; i++) { cursorIds.push($(cursors.get(i)).attr("id")); showInstanceIds.push($(cursors.get(i)).attr("si_id")); if ($(cursors.get(i)).hasClass("sb-footer")) { headerFooter.push("f"); } else { headerFooter.push("n"); } } }; mod.fnAdd = function (aMediaIds, aSchedIds) { AIRTIME.library.selectNone(); mod.disableUI(); $.post( baseUrl + "showbuilder/schedule-add", { format: "json", mediaIds: aMediaIds, schedIds: aSchedIds }, mod.fnItemCallback ); }; mod.fnMove = function (aSelect, aAfter) { mod.disableUI(); $.post( baseUrl + "showbuilder/schedule-move", { format: "json", selectedItem: aSelect, afterItem: aAfter }, mod.fnItemCallback ); }; mod.fnRemove = function (aItems) { mod.disableUI(); if (confirm($.i18n._("Delete selected item(s)?"))) { mod.selectNone(); $.post( baseUrl + "showbuilder/schedule-remove", { items: aItems, format: "json" }, mod.fnItemCallback ); } else { mod.enableUI(); } }; mod.fnRemoveSelectedItems = function () { var aData = mod.getSelectedData(), i, length, temp, aItems = []; for (i = 0, length = aData.length; i < length; i++) { temp = aData[i]; aItems.push({ id: temp.id, instance: temp.instance, timestamp: temp.timestamp, }); } mod.fnRemove(aItems); }; mod.fnServerData = function fnBuilderServerData(sSource, aoData, fnCallback) { aoData.push({ name: "timestamp", value: mod.getTimestamp() }); aoData.push({ name: "instances", value: mod.getShowInstances() }); aoData.push({ name: "format", value: "json" }); if (mod.fnServerData.hasOwnProperty("start")) { aoData.push({ name: "start", value: mod.fnServerData.start }); } if (mod.fnServerData.hasOwnProperty("end")) { aoData.push({ name: "end", value: mod.fnServerData.end }); } if (mod.fnServerData.hasOwnProperty("ops")) { aoData.push({ name: "myShows", value: mod.fnServerData.ops.myShows }); aoData.push({ name: "showFilter", value: mod.fnServerData.ops.showFilter, }); aoData.push({ name: "showInstanceFilter", value: mod.fnServerData.ops.showInstanceFilter, }); } $.ajax({ dataType: "json", type: "POST", url: sSource, data: aoData, success: function (json) { mod.updateCalendarStatusIcon(json); mod.setTimestamp(json.timestamp); mod.setShowInstances(json.instances); mod.getSelectedCursors(); fnCallback(json); }, }); }; mod.jumpToCurrentTrack = function () { var $scroll = $sbContent.find(".dataTables_scrolling"); var scrolled = $scroll.scrollTop(); var scrollingTop = $scroll.offset().top; var current = $sbTable.find("." + NOW_PLAYING_CLASS); var currentTop = current.offset().top; $scroll.scrollTop(currentTop - scrollingTop + scrolled); }; mod.builderDataTable = function () { $sbContent = $("#show_builder"); $lib = $("#library_content"); $sbTable = $sbContent.find("table"); var isInitialized = false; var lockedPreviewIcon = document.createElement("span"); lockedPreviewIcon.setAttribute("class", "ui-icon ui-icon-locked"); var previewIcon = document.createElement("img"); previewIcon.setAttribute("src", baseUrl + "css/images/icon_audioclip.png"); previewIcon.setAttribute("title", $.i18n._("Track preview")); oSchedTable = $sbTable.dataTable({ aoColumns: [ /* checkbox */ { mDataProp: "allowed", sTitle: "", sWidth: "16px", sClass: "sb-checkbox", }, /* Type */ { mDataProp: "image", sTitle: "", sClass: "library_image sb-image", sWidth: "16px", }, /* starts */ { mDataProp: "starts", sTitle: $.i18n._("Start"), sClass: "sb-starts", sWidth: "60px", }, /* ends */ { mDataProp: "ends", sTitle: $.i18n._("End"), sClass: "sb-ends", sWidth: "60px", }, /* runtime */ { mDataProp: "runtime", sTitle: $.i18n._("Duration"), sClass: "library_length sb-length", sWidth: "65px", }, /* title */ { mDataProp: "title", sTitle: $.i18n._("Title"), sClass: "sb-title", }, /* creator */ { mDataProp: "creator", sTitle: $.i18n._("Creator"), sClass: "sb-creator", }, /* album */ { mDataProp: "album", sTitle: $.i18n._("Album"), sClass: "sb-album", }, /* cue in */ { mDataProp: "cuein", sTitle: $.i18n._("Cue In"), bVisible: false, sClass: "sb-cue-in", }, /* cue out */ { mDataProp: "cueout", sTitle: $.i18n._("Cue Out"), bVisible: false, sClass: "sb-cue-out", }, /* fade in */ { mDataProp: "fadein", sTitle: $.i18n._("Fade In"), bVisible: false, sClass: "sb-fade-in", }, /* fade out */ { mDataProp: "fadeout", sTitle: $.i18n._("Fade Out"), bVisible: false, sClass: "sb-fade-out", }, /* Mime */ { mDataProp: "mime", sTitle: $.i18n._("Mime"), bVisible: false, sClass: "sb-mime", }, ], bJQueryUI: true, bSort: false, bFilter: false, bProcessing: true, bServerSide: true, bInfo: false, bAutoWidth: false, bDeferRender: true, bStateSave: true, fnStateSaveParams: function (oSettings, oData) { //remove oData components we don't want to save. delete oData.oSearch; delete oData.aoSearchCols; }, fnStateSave: function fnStateSave(oSettings, oData) { localStorage.setItem("datatables-timeline", JSON.stringify(oData)); }, fnStateLoad: function fnBuilderStateLoad(oSettings) { var settings = localStorage.getItem("datatables-timeline"); if (settings !== "") { return JSON.parse(settings); } }, fnStateLoadParams: function (oSettings, oData) { var i, length, a = oData.abVisCols; //putting serialized data back into the correct js type to make //sure everything works properly. for (i = 0, length = a.length; i < length; i++) { if (typeof a[i] === "string") { a[i] = a[i] === "true"; } } oData.iCreate = parseInt(oData.iCreate, 10); }, fnServerData: mod.fnServerData, fnRowCallback: function fnRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { var i, length, sSeparatorHTML, fnPrepareSeparatorRow, $node, cl = "", //background-color to imitate calendar color. r, g, b, a, $nRow = $(nRow), $image, $div, headerIcon; fnPrepareSeparatorRow = function fnPrepareSeparatorRow( sRowContent, sClass, iNodeIndex ) { //Albert: //$(nRow.children[iNodeIndex]).replaceWith(emptyNode); $node = $(nRow.children[iNodeIndex]); $node.html(sRowContent); $node.attr("colspan", 100); for ( i = iNodeIndex + 1, length = nRow.children.length; i < length; i = i + 1 ) { $node = $(nRow.children[i]); $node.html(""); $node.attr("style", "display : none"); } $nRow.addClass(sClass); }; if (aData.header === true) { //remove the column classes from all tds. $nRow.find("td").removeClass(); $node = $(nRow.children[0]); $node.html(""); cl = "sb-header"; if (aData.record === true) { $div = $("
", { class: "small-icon " + headerIcon, }); $node.append($div); } else if (aData.rebroadcast === true) { $div = $("", { class: "small-icon rebroadcast", }); $node.append($div); } sSeparatorHTML = '' + aData.title + ""; if (aData.rebroadcast === true) { sSeparatorHTML += "" + aData.rebroadcast_title + ""; } sSeparatorHTML += ''; if (aData.startDate === aData.endDate) { sSeparatorHTML += '' + aData.startDate + '' + aData.startTime + ""; sSeparatorHTML += '-' + aData.endTime + ""; } else { sSeparatorHTML += '' + aData.startDate + '' + aData.startTime + ""; sSeparatorHTML += '-' + aData.endDate + '' + aData.endTime + ""; } sSeparatorHTML += ""; fnPrepareSeparatorRow(sSeparatorHTML, cl, 1); } else if (aData.footer === true) { //remove the column classes from all tds. $nRow.find("td").removeClass(); $node = $(nRow.children[0]); cl = "sb-footer"; //check the show's content status. if (aData.runtime >= 0) { $node.html(''); cl = cl + " ui-state-highlight"; } else { $node.html(''); cl = cl + " ui-state-error"; } sSeparatorHTML = "" + aData.fRuntime + ""; fnPrepareSeparatorRow(sSeparatorHTML, cl, 1); } else if (aData.empty === true) { //remove the column classes from all tds. $nRow.find("td").removeClass(); $node = $(nRow.children[0]); if ($node) { $node.empty(); } sSeparatorHTML = "" + $.i18n._("Drag tracks here from the library") + ""; cl = cl + " sb-empty odd"; fnPrepareSeparatorRow(sSeparatorHTML, cl, 1); } else if (aData.record === true) { //remove the column classes from all tds. $nRow.find("td").removeClass(); $node = $(nRow.children[0]); $node.html(""); sSeparatorHTML = "" + $.i18n._("Recording From Line In") + ""; cl = cl + " sb-record odd"; fnPrepareSeparatorRow(sSeparatorHTML, cl, 1); } else { //add the play function if the file exists on disk. $image = $nRow.find("td.sb-image"); $image.empty(); //check if the file exists. if (aData.image === true) { $nRow.addClass("lib-audio"); if (!isAudioSupported(aData.mime)) { //$image.html(''); $image.append(lockedPreviewIcon); } else { $image.append(previewIcon.cloneNode(false)); $image.click(function () { open_show_preview(aData.instance, aData.pos); return false; }); } } else { $image.html(''); $image.find(".ui-icon-alert").qtip({ content: { text: $.i18n._( 'Airtime 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.' ), }, style: { classes: "ui-tooltip-dark", }, show: "mouseover", hide: "mouseout", }); } $node = $(nRow.children[0]); if ( aData.allowed === true && aData.scheduled >= 1 && aData.linked_allowed ) { $node.html( '' ); } else { $node.empty(); } } //add the show colour to the leftmost td if (aData.footer !== true) { if ($nRow.hasClass("sb-header")) { a = 1; } else if ($nRow.hasClass("odd")) { a = 0.3; } else if ($nRow.hasClass("even")) { a = 0.4; } //convert from hex to rgb. r = parseInt(aData.backgroundColor.substring(0, 2), 16); g = parseInt(aData.backgroundColor.substring(2, 4), 16); b = parseInt(aData.backgroundColor.substring(4, 6), 16); $nRow .find("td:first") .css( "background", "rgba(" + r + ", " + g + ", " + b + ", " + a + ")" ); } //save some info for reordering purposes. $nRow.data({ aData: aData }); if (aData.scheduled === 1) { $nRow.addClass(NOW_PLAYING_CLASS); } else if (aData.scheduled === 0 || aData.scheduled === undefined) { $nRow.addClass("sb-past"); } else { $nRow.addClass("sb-future"); } if (aData.allowed !== true || aData.linked_allowed === false) { $nRow.addClass("sb-not-allowed"); } else { $nRow.addClass("sb-allowed"); $nRow.attr("id", aData.id); $nRow.attr("si_id", aData.instance); } //status used to colour tracks. if (aData.status === 2) { $nRow.addClass("sb-boundry"); } else if (aData.status === 0) { $nRow.addClass("sb-over"); } if (aData.currentShow === true) { $nRow.addClass("sb-current-show"); } }, //remove any selected nodes before the draw. fnPreDrawCallback: function (oSettings) { //make sure any dragging helpers are removed or else they'll be stranded on the screen. $("#draggingContainer").remove(); }, fnDrawCallback: function fnBuilderDrawCallback(oSettings, json) { if (!isInitialized) { //when coming to 'Now Playing' page we want the page //to jump to the current track if ($(this).find("." + NOW_PLAYING_CLASS).length > 0) { mod.jumpToCurrentTrack(); } } isInitialized = true; var aData, elements, i, length, temp; clearTimeout(mod.timeout); //order of importance of elements for setting the next timeout. elements = [ $sbTable.find("tr." + NOW_PLAYING_CLASS), $sbTable .find("tbody") .find("tr.sb-future.sb-footer, tr.sb-future.sb-header") .filter(":first"), ]; //check which element we should set a timeout relative to. for (i = 0, length = elements.length; i < length; i++) { temp = elements[i]; if (temp.length > 0) { aData = temp.data("aData"); // max time interval // setTimeout allows only up to (2^31)-1 millisecs timeout value maxRefreshInterval = Math.pow(2, 31) - 1; refreshInterval = aData.refresh * 1000; if (refreshInterval > maxRefreshInterval) { refreshInterval = maxRefreshInterval; } mod.timeout = setTimeout(function () { mod.refresh(aData.id); }, refreshInterval); //need refresh in milliseconds break; } } mod.checkToolBarIcons(); var sid; if (selectedRows !== undefined) { selectedRows.each(function (i, el) { sid = $(el).attr("id"); var tr = $("#" + sid); tr.addClass(SB_SELECTED_CLASS); tr.find("input[type='checkbox']").prop("checked", true); }); mod.checkToolBarIcons(); } }, // R = ColReorder, C = ColVis sDom: 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t><"F">', oColVis: { aiExclude: [0, 1], buttonText: $.i18n._("Columns"), }, oColReorder: { iFixedColumns: 2, }, sAjaxDataProp: "schedule", oLanguage: getDatatablesStrings({ sZeroRecords: $.i18n._( "There are no shows scheduled during the specified time period." ), sEmptyTable: $.i18n._( "There are no shows scheduled during the specified time period." ), }), sAjaxSource: baseUrl + "showbuilder/builder-feed", bScrollCollapseY: false, }); $sbTable .find("tbody") .on( "mousedown", "tr:not(.sb-not-allowed, .sb-header, .sb-footer, .sb-past, .sb-empty, :has(td.dataTables_empty)) > td.sb-checkbox", function (ev) { var $tr = $(this).parent(), // Get the ID of the selected row $rowId = $tr.attr("id"); if (!$tr.hasClass(SB_SELECTED_CLASS)) { if (ev.shiftKey && $previouslySelected !== undefined) { if ($previouslySelected.attr("id") == $rowId) { return; } // If the selected row comes before the previously selected row, // we want to select previous rows, otherwise we select next if ($previouslySelected.prevAll("#" + $rowId).length !== 0) { $previouslySelected.prevUntil($tr).each(function (i, el) { $(el).addClass(SB_SELECTED_CLASS); $(el).find(".sb-checkbox > input").prop("checked", true); }); } else { $previouslySelected.nextUntil($tr).each(function (i, el) { $(el).addClass(SB_SELECTED_CLASS); $(el).find(".sb-checkbox > input").prop("checked", true); }); } } $tr.addClass(SB_SELECTED_CLASS); $tr.find(".sb-checkbox > input").prop("checked", true); } else { flagForDeselection = true; } selectedRows = $("." + SB_SELECTED_CLASS); // Remember this row so we can properly multiselect $previouslySelected = $tr; } ); $sbTable .find("tbody") .on( "mousedown", "tr:not(.sb-not-allowed, .sb-header, .sb-footer, .sb-past, .sb-empty, :has(td.dataTables_empty)) > td:not(.sb-checkbox)", function (ev) { var $tr = $(this).parent(), // Get the ID of the selected row $rowId = $tr.attr("id"); if (ev.which === 3 /* Right click */) { mod.selectNone(); $tr.addClass(SB_SELECTED_CLASS); $tr.find(".sb-checkbox > input").prop("checked", true); mod.checkToolBarIcons(); return; } if (!$tr.hasClass(SB_SELECTED_CLASS)) { if (ev.shiftKey && $previouslySelected !== undefined) { if ($previouslySelected.attr("id") == $rowId) { return; } // If the selected row comes before the previously selected row, // we want to select previous rows, otherwise we select next if ($previouslySelected.prevAll("#" + $rowId).length !== 0) { $previouslySelected.prevUntil($tr).each(function (i, el) { $(el).addClass(SB_SELECTED_CLASS); $(el).find(".sb-checkbox > input").prop("checked", true); }); } else { $previouslySelected.nextUntil($tr).each(function (i, el) { $(el).addClass(SB_SELECTED_CLASS); $(el).find(".sb-checkbox > input").prop("checked", true); }); } } else if (!ev.ctrlKey) { mod.selectNone(); } $tr.addClass(SB_SELECTED_CLASS); $tr.find(".sb-checkbox > input").prop("checked", true); mod.checkToolBarIcons(); } else if (ev.ctrlKey) { flagForDeselection = true; } selectedRows = $("." + SB_SELECTED_CLASS); // Remember this row so we can properly multiselect $previouslySelected = $tr; } ); $sbTable .find("tbody") .on( "click", "tr:not(.sb-not-allowed, .sb-header, .sb-footer, .sb-past, .sb-empty, :has(td.dataTables_empty)) > td.sb-checkbox", function () { var tr = $(this).parent(); if (flagForDeselection) { flagForDeselection = false; $previouslySelected = undefined; tr.removeClass(SB_SELECTED_CLASS); tr.find(".sb-checkbox > input").prop("checked", false); } else { tr.addClass(SB_SELECTED_CLASS); tr.find(".sb-checkbox > input").prop("checked", true); } mod.checkToolBarIcons(); selectedRows = $("." + SB_SELECTED_CLASS); } ); $sbTable .find("tbody") .on( "click", "tr:not(.sb-not-allowed, .sb-header, .sb-footer, .sb-past, .sb-empty, :has(td.dataTables_empty)) > td:not(.sb-checkbox)", function (e) { var tr = $(this).parent(); if (flagForDeselection) { flagForDeselection = false; $previouslySelected = undefined; tr.removeClass(SB_SELECTED_CLASS); tr.find(".sb-checkbox > input").prop("checked", false); } else if (!(e.shiftKey || e.ctrlKey)) { mod.selectNone(); tr.addClass(SB_SELECTED_CLASS); tr.find(".sb-checkbox > input").prop("checked", true); $previouslySelected = tr; } mod.checkToolBarIcons(); selectedRows = $("." + SB_SELECTED_CLASS); } ); //begin context menu initialization. $.contextMenu({ selector: "#show_builder tr.lib-audio:not(.sb-not-allowed, .sb-past)", trigger: "right", build: function ($el, e) { var items, $tr = $el, data = $tr.data("aData"), cursorClass = "cursor-selected-row", callback; function processMenuItems(oItems) { //define a preview callback. if (oItems.preview !== undefined) { callback = function () { open_show_preview(data.instance, data.pos); }; oItems.preview.callback = callback; } //define a select cursor callback. if (oItems.selCurs !== undefined) { callback = function () { var $tr = $(this).parents("tr").next(); mod.selectCursor($tr); }; oItems.selCurs.callback = callback; } //define a remove cursor callback. if (oItems.delCurs !== undefined) { callback = function () { var $tr = $(this).parents("tr").next(); mod.removeCursor($tr); }; oItems.delCurs.callback = callback; } //define a delete callback. if (oItems.del !== undefined) { callback = function () { AIRTIME.showbuilder.fnRemove([ { id: data.id, timestamp: data.timestamp, instance: data.instance, }, ]); }; oItems.del.callback = callback; } //only show the cursor selecting options if the library is visible on the page. if ($tr.next().find(".marker").length === 0) { delete oItems.selCurs; delete oItems.delCurs; } //check to include either select or remove cursor. else { if ($tr.next().hasClass(cursorClass)) { delete oItems.selCurs; } else { delete oItems.delCurs; } } items = oItems; } request = $.ajax({ url: baseUrl + "showbuilder/context-menu", type: "GET", data: { id: data.id, format: "json" }, dataType: "json", async: false, success: function (json) { processMenuItems(json.items); }, }); return { items: items, }; }, }); var sortableConf = (function () { var origTrs, aItemData = [], oPrevData, fnAdd, fnMove, fnReceive, fnUpdate, i, html, helperData, draggingContainer; fnAdd = function () { var aMediaIds = [], aSchedIds = []; for (i = 0; i < aItemData.length; i++) { aMediaIds.push({ id: aItemData[i].id, type: aItemData[i].ftype }); } aSchedIds.push({ id: oPrevData.id, instance: oPrevData.instance, timestamp: oPrevData.timestamp, }); mod.fnAdd(aMediaIds, aSchedIds); }; fnMove = function () { var aSelect = [], aAfter = []; for (i = 0; i < helperData.length; i++) { aSelect.push({ id: helperData[i].id, instance: helperData[i].instance, timestamp: helperData[i].timestamp, }); } aAfter.push({ id: oPrevData.id, instance: oPrevData.instance, timestamp: oPrevData.timestamp, }); mod.fnMove(aSelect, aAfter); }; fnReceive = function (event, ui) { var aItems = []; if ( AIRTIME.library.getCurrentTable() == AIRTIME.library.libraryDataTable ) { AIRTIME.library.addToChosen(ui.item); aItems = AIRTIME.library.getSelectedData(); origTrs = aItems; html = ui.helper.html(); AIRTIME.library.removeFromChosen(ui.item); } else if ( AIRTIME.library.getCurrentTable() == AIRTIME.library.podcastEpisodeDataTable ) { origTrs = [$(ui.item).data("aData")]; html = ui.helper.html(); } }; fnUpdate = function (event, ui) { var prev = ui.item.prev(); //can't add items outside of shows. if ( prev.find("td:first").hasClass("dataTables_empty") || prev.length === 0 ) { alert($.i18n._("Cannot schedule outside a show.")); ui.item.remove(); return; } //if item is added after a footer, add the item after the last item in the show. if (prev.hasClass("sb-footer")) { prev = prev.prev(); } aItemData = []; oPrevData = prev.data("aData"); //item was dragged in if (origTrs !== undefined) { $sbTable.find("tr.ui-draggable").empty().after(html); aItemData = origTrs; origTrs = undefined; fnAdd(); } //item was reordered. else { //ui.item // .empty() // .after(draggingContainer.html()); aItemData.push(ui.item.data("aData")); fnMove(); } }; return { placeholder: "sb-placeholder ui-state-highlight", //forcePlaceholderSize: true, distance: 25, helper: function (event, item) { var selected = mod.getSelectedData(NOW_PLAYING_CLASS), thead = $("#show_builder_table thead"), colspan = thead.find("th").length, trfirst = thead.find("tr:first"), width = trfirst.width(), height = trfirst.height(), message; //if nothing is checked select the dragged item. if (selected.length === 0) { selected = [item.data("aData")]; } if (selected.length === 1) { message = sprintf($.i18n._("Moving %s"), selected[0].title); //draggingContainer = item; //Default DataTables drag and drop draggingContainer = $("