style(legacy): format (#2039)

This commit is contained in:
Jonas L 2022-08-10 13:38:19 +02:00 committed by GitHub
parent 7082c9693d
commit 1550d44ac5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
122 changed files with 18369 additions and 15819 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,376 +1,382 @@
AIRTIME = (function(AIRTIME) {
AIRTIME = (function (AIRTIME) {
var viewport,
$lib,
$libWrapper,
$builder,
$fs,
widgetHeight,
screenWidth,
resizeTimeout,
oBaseDatePickerSettings,
oBaseTimePickerSettings,
oRange,
dateStartId = "#sb_date_start",
timeStartId = "#sb_time_start",
dateEndId = "#sb_date_end",
timeEndId = "#sb_time_end",
mod;
var viewport,
$lib,
$libWrapper,
$builder,
$fs,
widgetHeight,
screenWidth,
resizeTimeout,
oBaseDatePickerSettings,
oBaseTimePickerSettings,
oRange,
dateStartId = "#sb_date_start",
timeStartId = "#sb_time_start",
dateEndId = "#sb_date_end",
timeEndId = "#sb_time_end",
mod;
if (AIRTIME.builderMain === undefined) {
AIRTIME.builderMain = {};
}
mod = AIRTIME.builderMain;
if (AIRTIME.builderMain === undefined) {
AIRTIME.builderMain = {};
oBaseDatePickerSettings = {
dateFormat: "yy-mm-dd",
//i18n_months, i18n_days_short are in common.js
monthNames: i18n_months,
dayNamesMin: i18n_days_short,
onClick: function (sDate, oDatePicker) {
$(this).datepicker("setDate", sDate);
},
onClose: validateTimeRange,
};
oBaseTimePickerSettings = {
showPeriodLabels: false,
showCloseButton: true,
closeButtonText: $.i18n._("Done"),
showLeadingZero: false,
defaultTime: "0:00",
hourText: $.i18n._("Hour"),
minuteText: $.i18n._("Minute"),
onClose: validateTimeRange,
};
function setWidgetSize() {
viewport = AIRTIME.utilities.findViewportDimensions();
widgetHeight = viewport.height - 180;
screenWidth = Math.floor(viewport.width - 50);
var libTableHeight = widgetHeight - 175,
builderTableHeight = widgetHeight - 95,
oTable;
if ($fs.is(":visible")) {
builderTableHeight = builderTableHeight - 40;
}
mod = AIRTIME.builderMain;
oBaseDatePickerSettings = {
dateFormat: 'yy-mm-dd',
//i18n_months, i18n_days_short are in common.js
monthNames: i18n_months,
dayNamesMin: i18n_days_short,
onClick: function(sDate, oDatePicker) {
$(this).datepicker( "setDate", sDate );
//set the heights of the main widgets.
$builder //.height(widgetHeight)
.find(".dataTables_scrolling")
//.css("max-height", builderTableHeight)
.end();
//.width(screenWidth);
$lib //.height(widgetHeight)
.find(".dataTables_scrolling")
//.css("max-height", libTableHeight)
.end();
if ($lib.filter(":visible").length > 0) {
//$lib.width(Math.floor(screenWidth * 0.47));
$builder //.width(Math.floor(screenWidth * 0.47))
.find("#sb_edit")
.remove()
.end()
.find("#sb_date_start")
.css("margin-left", 0)
.end();
oTable = $("#show_builder_table").dataTable();
//oTable.fnDraw();
}
}
function showSearchSubmit() {
var fn,
op,
oTable = $("#show_builder_table").dataTable(),
check;
check = validateTimeRange();
if (check.isValid) {
//reset timestamp value since input values could have changed.
AIRTIME.showbuilder.resetTimestamp();
fn = oTable.fnSettings().fnServerData;
fn.start = check.start;
fn.end = check.end;
op = $("div.sb-options-form");
if (op.is(":visible")) {
if (fn.ops === undefined) {
fn.ops = {};
}
fn.ops.showFilter = op.find("#sb_show_filter").val();
// Hacky?
fn.ops.myShows = fn.ops.showFilter == -1 ? 1 : 0;
}
oTable.fnDraw();
}
}
function highlightMediaTypeSelector() {
$(".media_type_selector:first").addClass("highlight");
var selected;
if (location.hash === "") {
location.hash = "tracks";
selected = $("a[href$='#tracks']");
} else {
selected = $("a[href$='" + location.hash + "']");
}
selected.parent().addClass("selected");
$("#library_filter").text(selected.text());
$(window).on("hashchange", function () {
var selected = $("a[href$='" + location.hash + "']"),
dashboardLink = $(".media_type_selector:first"),
tableType;
if (
selected.parent().data("selection-id") ==
AIRTIME.library.MediaTypeIntegerEnum.PODCAST
) {
tableType = AIRTIME.library.DataTableTypeEnum.PODCAST;
} else {
tableType = AIRTIME.library.DataTableTypeEnum.LIBRARY;
}
dashboardLink.find("a").attr("href", selected.attr("href"));
AIRTIME.library.selectNone();
$(".media_type_selector").each(function () {
$(this).removeClass("selected");
});
selected.parent().addClass("selected");
AIRTIME.library.setCurrentTable(tableType);
$("#library_filter").text(selected.text());
// Highlight the dashboard link
dashboardLink.addClass("highlight");
});
}
mod.onReady = function () {
// Normally we would just use audio/*, but it includes file types that we can't handle (like .m4a)
// We initialize the acceptedMimeTypes variable in Bootstrap so we don't have to duplicate the list
Dropzone.options.content = {
url: "/rest/media",
clickable: false,
acceptedFiles: acceptedMimeTypes.join(),
init: function () {
this.on("sending", function (file, xhr, data) {
data.append("csrf_token", $("#csrf").val());
});
},
dictDefaultMessage: "",
createImageThumbnails: false,
previewTemplate: '<div style="display:none"></div>',
};
// define module vars.
$lib = $("#library_content");
$builder = $("#show_builder");
$fs = $builder.find("fieldset");
//Highlight the media type selector we're currently on.
highlightMediaTypeSelector();
// always re-show builder if dashboard button was clicked
$(".media_type_selector:first").on("click", function () {
$builder.show();
AIRTIME.tabs.openScheduleTab();
});
/*
* Icon hover states for search.
*/
$builder.on("mouseenter", ".sb-timerange .ui-button", function (ev) {
$(this).addClass("ui-state-hover");
});
$builder.on("mouseleave", ".sb-timerange .ui-button", function (ev) {
$(this).removeClass("ui-state-hover");
});
$builder
.find(dateStartId)
.datepicker(oBaseDatePickerSettings)
.blur(validateTimeRange);
$builder
.find(timeStartId)
.timepicker(oBaseTimePickerSettings)
.blur(validateTimeRange);
$builder
.find(dateEndId)
.datepicker(oBaseDatePickerSettings)
.blur(validateTimeRange);
$builder
.find(timeEndId)
.timepicker(oBaseTimePickerSettings)
.blur(validateTimeRange);
oRange = AIRTIME.utilities.fnGetScheduleRange(
dateStartId,
timeStartId,
dateEndId,
timeEndId
);
AIRTIME.showbuilder.fnServerData.start = oRange.start;
AIRTIME.showbuilder.fnServerData.end = oRange.end;
//the user might not have the library on the page (guest user)
if (AIRTIME.library !== undefined) {
AIRTIME.library.libraryInit();
}
AIRTIME.showbuilder.builderDataTable();
setWidgetSize();
$libWrapper = $lib.find("#library_display_wrapper");
//$builder.find('.dataTables_scrolling').css("max-height",
// widgetHeight - 95);
$builder.on("click", "#sb_submit", showSearchSubmit);
$builder.on("click", "#sb_edit", function (ev) {
var schedTable = $("#show_builder_table").dataTable();
// reset timestamp to redraw the cursors.
AIRTIME.showbuilder.resetTimestamp();
$lib.show().width(Math.floor(screenWidth * 0.48));
$builder
.width(Math.floor(screenWidth * 0.48))
.find("#sb_edit")
.remove()
.end()
.find("#sb_date_start")
.css("margin-left", 0)
.end();
schedTable.fnDraw();
$.ajax({
url: baseUrl + "usersettings/set-now-playing-screen-settings",
type: "POST",
data: {
settings: {
library: true,
},
format: "json",
},
onClose: validateTimeRange
};
dataType: "json",
success: function () {},
});
});
oBaseTimePickerSettings = {
showPeriodLabels: false,
showCloseButton: true,
closeButtonText: $.i18n._("Done"),
showLeadingZero: false,
defaultTime: '0:00',
hourText: $.i18n._("Hour"),
minuteText: $.i18n._("Minute"),
onClose: validateTimeRange
};
$lib.on("click", "#sb_lib_close", function () {
var schedTable = $("#show_builder_table").dataTable();
function setWidgetSize() {
viewport = AIRTIME.utilities.findViewportDimensions();
widgetHeight = viewport.height - 180;
screenWidth = Math.floor(viewport.width - 50);
$lib.hide();
$builder
.width(screenWidth)
.find(".sb-timerange")
.find("#sb_date_start")
.css("margin-left", 30)
.end()
.end();
var libTableHeight = widgetHeight - 175,
builderTableHeight = widgetHeight - 95,
oTable;
schedTable.fnDraw();
if ($fs.is(':visible')) {
builderTableHeight = builderTableHeight - 40;
}
$.ajax({
url: baseUrl + "usersettings/set-now-playing-screen-settings",
type: "POST",
data: {
settings: {
library: false,
},
format: "json",
},
dataType: "json",
success: function () {},
});
});
//set the heights of the main widgets.
$builder//.height(widgetHeight)
.find(".dataTables_scrolling")
//.css("max-height", builderTableHeight)
.end();
//.width(screenWidth);
$builder.find("legend").click(function (ev, item) {
if ($fs.hasClass("closed")) {
$fs.removeClass("closed");
//$builder.find('.dataTables_scrolling').css(
// "max-height", widgetHeight - 150);
} else {
$fs.addClass("closed");
$lib//.height(widgetHeight)
.find(".dataTables_scrolling")
//.css("max-height", libTableHeight)
.end();
// set defaults for the options.
$fs.find("select").val(0);
$fs.find('input[type="checkbox"]').attr("checked", false);
//$builder.find('.dataTables_scrolling').css(
// "max-height", widgetHeight - 110);
}
});
if ($lib.filter(':visible').length > 0) {
// set click event for all my shows checkbox.
$builder.on("click", "#sb_my_shows", function (ev) {
if ($(this).is(":checked")) {
$(ev.delegateTarget).find("#sb_show_filter").val(0);
}
//$lib.width(Math.floor(screenWidth * 0.47));
showSearchSubmit();
});
$builder//.width(Math.floor(screenWidth * 0.47))
.find("#sb_edit")
.remove()
.end()
.find("#sb_date_start")
.css("margin-left", 0)
.end();
//set select event for choosing a show.
$builder.on("change", "#sb_show_filter", function (ev) {
if ($(this).val() !== 0) {
$(ev.delegateTarget).find("#sb_my_shows").attr("checked", false);
}
oTable = $('#show_builder_table').dataTable();
//oTable.fnDraw();
}
}
showSearchSubmit();
});
function showSearchSubmit() {
var fn,
op,
oTable = $('#show_builder_table').dataTable(),
check;
function checkScheduleUpdates() {
var data = {},
oTable = $("#show_builder_table").dataTable(),
fn = oTable.fnSettings().fnServerData,
start = fn.start,
end = fn.end;
check = validateTimeRange();
data["format"] = "json";
data["start"] = start;
data["end"] = end;
data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
data["instances"] = AIRTIME.showbuilder.getShowInstances();
if (check.isValid) {
//reset timestamp value since input values could have changed.
AIRTIME.showbuilder.resetTimestamp();
fn = oTable.fnSettings().fnServerData;
fn.start = check.start;
fn.end = check.end;
op = $("div.sb-options-form");
if (op.is(":visible")) {
if (fn.ops === undefined) {
fn.ops = {};
}
fn.ops.showFilter = op.find("#sb_show_filter").val();
// Hacky?
fn.ops.myShows = (fn.ops.showFilter == -1) ? 1 : 0;
}
if (fn.hasOwnProperty("ops")) {
data["myShows"] = fn.ops.myShows;
data["showFilter"] = fn.ops.showFilter;
data["showInstanceFilter"] = fn.ops.showInstanceFilter;
}
$.ajax({
dataType: "json",
type: "GET",
url: baseUrl + "showbuilder/check-builder-feed",
data: data,
success: function (json) {
if (json.update === true) {
oTable.fnDraw();
}
}
setTimeout(checkScheduleUpdates, 5000);
},
});
//check if the timeline view needs updating.
setTimeout(checkScheduleUpdates, 5000);
}
};
function highlightMediaTypeSelector()
{
$(".media_type_selector:first").addClass("highlight");
var selected;
if (location.hash === "") {
location.hash = "tracks";
selected = $("a[href$='#tracks']");
} else {
selected = $("a[href$='"+location.hash+"']");
}
mod.onResize = function () {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(setWidgetSize, 100);
};
selected.parent().addClass("selected");
$("#library_filter").text(selected.text());
$(window).on('hashchange', function() {
var selected = $("a[href$='"+location.hash+"']"),
dashboardLink = $(".media_type_selector:first"),
tableType;
if (selected.parent().data("selection-id") == AIRTIME.library.MediaTypeIntegerEnum.PODCAST) {
tableType = AIRTIME.library.DataTableTypeEnum.PODCAST;
} else {
tableType = AIRTIME.library.DataTableTypeEnum.LIBRARY;
}
dashboardLink.find("a").attr("href", selected.attr("href"));
AIRTIME.library.selectNone();
$(".media_type_selector").each(function () {
$(this).removeClass("selected");
});
selected.parent().addClass("selected");
AIRTIME.library.setCurrentTable(tableType);
$("#library_filter").text(selected.text());
// Highlight the dashboard link
dashboardLink.addClass("highlight");
});
}
mod.onReady = function() {
// Normally we would just use audio/*, but it includes file types that we can't handle (like .m4a)
// We initialize the acceptedMimeTypes variable in Bootstrap so we don't have to duplicate the list
Dropzone.options.content = {
url:'/rest/media',
clickable: false,
acceptedFiles: acceptedMimeTypes.join(),
init: function () {
this.on("sending", function (file, xhr, data) {
data.append("csrf_token", $("#csrf").val());
});
},
dictDefaultMessage: '',
createImageThumbnails: false,
previewTemplate : '<div style="display:none"></div>'
};
// define module vars.
$lib = $("#library_content");
$builder = $("#show_builder");
$fs = $builder.find('fieldset');
//Highlight the media type selector we're currently on.
highlightMediaTypeSelector();
// always re-show builder if dashboard button was clicked
$('.media_type_selector:first').on('click', function() {
$builder.show();
AIRTIME.tabs.openScheduleTab();
});
/*
* Icon hover states for search.
*/
$builder.on("mouseenter", ".sb-timerange .ui-button", function(ev) {
$(this).addClass("ui-state-hover");
});
$builder.on("mouseleave", ".sb-timerange .ui-button", function(ev) {
$(this).removeClass("ui-state-hover");
});
$builder.find(dateStartId)
.datepicker(oBaseDatePickerSettings)
.blur(validateTimeRange);
$builder.find(timeStartId)
.timepicker(oBaseTimePickerSettings)
.blur(validateTimeRange);
$builder.find(dateEndId)
.datepicker(oBaseDatePickerSettings)
.blur(validateTimeRange);
$builder.find(timeEndId)
.timepicker(oBaseTimePickerSettings)
.blur(validateTimeRange);
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId,
dateEndId, timeEndId);
AIRTIME.showbuilder.fnServerData.start = oRange.start;
AIRTIME.showbuilder.fnServerData.end = oRange.end;
//the user might not have the library on the page (guest user)
if (AIRTIME.library !== undefined) {
AIRTIME.library.libraryInit();
}
AIRTIME.showbuilder.builderDataTable();
setWidgetSize();
$libWrapper = $lib.find("#library_display_wrapper");
//$builder.find('.dataTables_scrolling').css("max-height",
// widgetHeight - 95);
$builder.on("click", "#sb_submit", showSearchSubmit);
$builder.on("click", "#sb_edit", function(ev) {
var schedTable = $("#show_builder_table").dataTable();
// reset timestamp to redraw the cursors.
AIRTIME.showbuilder.resetTimestamp();
$lib.show().width(Math.floor(screenWidth * 0.48));
$builder.width(Math.floor(screenWidth * 0.48)).find("#sb_edit")
.remove().end().find("#sb_date_start")
.css("margin-left", 0).end();
schedTable.fnDraw();
$.ajax( {
url : baseUrl+"usersettings/set-now-playing-screen-settings",
type : "POST",
data : {
settings : {
library : true
},
format : "json"
},
dataType : "json",
success : function() {
}
});
});
$lib.on("click", "#sb_lib_close", function() {
var schedTable = $("#show_builder_table").dataTable();
$lib.hide();
$builder.width(screenWidth).find(".sb-timerange").find("#sb_date_start").css("margin-left", 30)
.end().end();
schedTable.fnDraw();
$.ajax( {
url : baseUrl+"usersettings/set-now-playing-screen-settings",
type : "POST",
data : {
settings : {
library : false
},
format : "json"
},
dataType : "json",
success : function() {
}
});
});
$builder.find('legend').click(
function(ev, item) {
if ($fs.hasClass("closed")) {
$fs.removeClass("closed");
//$builder.find('.dataTables_scrolling').css(
// "max-height", widgetHeight - 150);
} else {
$fs.addClass("closed");
// set defaults for the options.
$fs.find('select').val(0);
$fs.find('input[type="checkbox"]').attr("checked",
false);
//$builder.find('.dataTables_scrolling').css(
// "max-height", widgetHeight - 110);
}
});
// set click event for all my shows checkbox.
$builder.on("click", "#sb_my_shows", function(ev) {
if ($(this).is(':checked')) {
$(ev.delegateTarget).find('#sb_show_filter').val(0);
}
showSearchSubmit();
});
//set select event for choosing a show.
$builder.on("change", '#sb_show_filter', function(ev) {
if ($(this).val() !== 0) {
$(ev.delegateTarget).find('#sb_my_shows')
.attr("checked", false);
}
showSearchSubmit();
});
function checkScheduleUpdates() {
var data = {}, oTable = $('#show_builder_table').dataTable(), fn = oTable
.fnSettings().fnServerData, start = fn.start, end = fn.end;
data["format"] = "json";
data["start"] = start;
data["end"] = end;
data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
data["instances"] = AIRTIME.showbuilder.getShowInstances();
if (fn.hasOwnProperty("ops")) {
data["myShows"] = fn.ops.myShows;
data["showFilter"] = fn.ops.showFilter;
data["showInstanceFilter"] = fn.ops.showInstanceFilter;
}
$.ajax( {
"dataType" : "json",
"type" : "GET",
"url" : baseUrl+"showbuilder/check-builder-feed",
"data" : data,
"success" : function(json) {
if (json.update === true) {
oTable.fnDraw();
}
setTimeout(checkScheduleUpdates, 5000);
}
});
//check if the timeline view needs updating.
setTimeout(checkScheduleUpdates, 5000);
}
};
mod.onResize = function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(setWidgetSize, 100);
};
return AIRTIME;
} (AIRTIME || {}));
return AIRTIME;
})(AIRTIME || {});
$(document).ready(AIRTIME.builderMain.onReady);
$(window).resize(AIRTIME.builderMain.onResize);

View file

@ -1,426 +1,446 @@
var AIRTIME = (function(AIRTIME){
/**
* AIRTIME module namespace object
*/
var mod,
/**
* Tab counter to use as unique tab IDs that can be
* retrieved from the DOM
*
* @type {number}
*/
$tabCount = 0,
/**
* Map of Tab IDs (by tabCount) to object UIDs so
* Tabs can be referenced either by ID (from the DOM)
* or by UID (from object data)
*
* @type {{}}
*/
$tabMap = {},
/**
* Map of object UIDs to currently open Tab objects
*
* @type {{}}
*/
$openTabs = {},
/**
* The currently active (open) Tab object
*
* @type {Tab}
*/
$activeTab,
/**
* Singleton object used to reference the schedule tab
*
* @type {ScheduleTab}
*/
$scheduleTab;
var AIRTIME = (function (AIRTIME) {
/**
* AIRTIME module namespace object
*/
var mod,
/**
* Tab counter to use as unique tab IDs that can be
* retrieved from the DOM
*
* @type {number}
*/
$tabCount = 0,
/**
* Map of Tab IDs (by tabCount) to object UIDs so
* Tabs can be referenced either by ID (from the DOM)
* or by UID (from object data)
*
* @type {{}}
*/
$tabMap = {},
/**
* Map of object UIDs to currently open Tab objects
*
* @type {{}}
*/
$openTabs = {},
/**
* The currently active (open) Tab object
*
* @type {Tab}
*/
$activeTab,
/**
* Singleton object used to reference the schedule tab
*
* @type {ScheduleTab}
*/
$scheduleTab;
if (AIRTIME.tabs === undefined) {
AIRTIME.tabs = {};
}
mod = AIRTIME.tabs;
if (AIRTIME.tabs === undefined) {
AIRTIME.tabs = {};
}
mod = AIRTIME.tabs;
/* #####################################################
/* #####################################################
Object Initialization and Functions
##################################################### */
/**
* Tab object constructor
*
* @param {string} html the HTML to render as the tab contents
* @param {string} uid the unique ID for the tab. Uses the values in
* AIRTIME.library.MediaTypeStringEnum and the object ID
* to create a string of the form TYPE_ID.
* @returns {Tab} the created Tab object
* @constructor
*/
var Tab = function(html, uid) {
var self = this;
/**
* Tab object constructor
*
* @param {string} html the HTML to render as the tab contents
* @param {string} uid the unique ID for the tab. Uses the values in
* AIRTIME.library.MediaTypeStringEnum and the object ID
* to create a string of the form TYPE_ID.
* @returns {Tab} the created Tab object
* @constructor
*/
var Tab = function (html, uid) {
var self = this;
AIRTIME.library.selectNone();
AIRTIME.library.selectNone();
var existingTab = $openTabs[uid];
if (existingTab) {
existingTab.switchTo();
return existingTab;
}
self.id = ++$tabCount;
self.uid = uid;
var existingTab = $openTabs[uid];
if (existingTab) {
existingTab.switchTo();
return existingTab;
}
self.id = ++$tabCount;
self.uid = uid;
// TODO: clean this up a bit and use js instead of strings to create elements
var wrapper = "<div data-tab-id='" + self.id + "' id='pl-tab-content-" + self.id + "' class='side_playlist pl-content'><div class='editor_pane_wrapper'></div></div>",
t = $("#show_builder").append(wrapper).find("#pl-tab-content-" + self.id),
pane = $(".editor_pane_wrapper:last").append(html),
name = pane.find("#track_title").length > 0 ? pane.find("#track_title").val() + $.i18n._(" - Metadata Editor")
: pane.find(".playlist_name_display").val(),
tab =
"<li data-tab-id='" + self.id + "' id='pl-tab-" + self.id + "' role='presentation' class='active'>" +
"<a href='javascript:void(0)'>" +
"<span class='tab-name'>" + name + "</span>" +
"<span href='#' class='lib_pl_close icon-remove'></span>" +
"</a>" +
"</li>",
tabs = $(".nav.nav-tabs");
// TODO: clean this up a bit and use js instead of strings to create elements
var wrapper =
"<div data-tab-id='" +
self.id +
"' id='pl-tab-content-" +
self.id +
"' class='side_playlist pl-content'><div class='editor_pane_wrapper'></div></div>",
t = $("#show_builder")
.append(wrapper)
.find("#pl-tab-content-" + self.id),
pane = $(".editor_pane_wrapper:last").append(html),
name =
pane.find("#track_title").length > 0
? pane.find("#track_title").val() + $.i18n._(" - Metadata Editor")
: pane.find(".playlist_name_display").val(),
tab =
"<li data-tab-id='" +
self.id +
"' id='pl-tab-" +
self.id +
"' role='presentation' class='active'>" +
"<a href='javascript:void(0)'>" +
"<span class='tab-name'>" +
name +
"</span>" +
"<span href='#' class='lib_pl_close icon-remove'></span>" +
"</a>" +
"</li>",
tabs = $(".nav.nav-tabs");
$(".nav.nav-tabs li").removeClass("active");
tabs.append(tab);
$(".nav.nav-tabs li").removeClass("active");
tabs.append(tab);
var newTab = $("#pl-tab-" + self.id);
var newTab = $("#pl-tab-" + self.id);
self.wrapper = pane;
self.contents = t;
self.tab = newTab;
self.wrapper = pane;
self.contents = t;
self.tab = newTab;
$openTabs[uid] = self;
$tabMap[self.id] = uid;
$openTabs[uid] = self;
$tabMap[self.id] = uid;
self._init();
self._init();
self.switchTo();
return self;
};
/**
* Private initialization function for Tab objects
*
* Assigns default action handlers to the tab DOM element
*
* @private
*/
Tab.prototype._init = function () {
var self = this;
self.assignTabClickHandler(function (e) {
if (!$(this).hasClass("active")) {
self.switchTo();
return self;
};
}
});
/**
* Private initialization function for Tab objects
*
* Assigns default action handlers to the tab DOM element
*
* @private
*/
Tab.prototype._init = function() {
var self = this;
self.assignTabClickHandler(function(e) {
if (!$(this).hasClass('active')) {
self.switchTo();
}
});
self.assignTabCloseClickHandler(function (e) {
e.preventDefault();
e.stopPropagation();
$(this).unbind("click"); // Prevent repeated clicks in quick succession from closing multiple tabs
self.assignTabCloseClickHandler(function(e) {
e.preventDefault();
e.stopPropagation();
$(this).unbind("click"); // Prevent repeated clicks in quick succession from closing multiple tabs
// 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();
self.close();
});
// 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();
self.close();
});
self.contents.on("click", ".toggle-editor-form", function (event) {
self.contents.find(".inner_editor_wrapper").slideToggle(200);
var buttonIcon = $(this).find(".icon-white");
buttonIcon.toggleClass("icon-chevron-up");
buttonIcon.toggleClass("icon-chevron-down");
});
};
self.contents.on("click", ".toggle-editor-form", function(event) {
self.contents.find(".inner_editor_wrapper").slideToggle(200);
var buttonIcon = $(this).find('.icon-white');
buttonIcon.toggleClass('icon-chevron-up');
buttonIcon.toggleClass('icon-chevron-down');
});
};
/**
* Internal destructor. Can be assigned via assignOnCloseHandler
*
* @private
*/
Tab.prototype._destroy = function () {};
/**
* Internal destructor. Can be assigned via assignOnCloseHandler
*
* @private
*/
Tab.prototype._destroy = function () {};
/**
* Assign the given function f as the click handler for the tab
*
* @param {function} f the function to call when the tab is clicked
*/
Tab.prototype.assignTabClickHandler = function (f) {
var self = this;
self.tab.unbind("click").on("click", function (e) {
// Always close on middle mouse press
if (e.which == 2) {
// Simulate a click on the close tab button so any
// additional on-close behaviour is executed
self.tab.find(".lib_pl_close").click();
return;
}
f();
});
};
/**
* Assign the given function f as the click handler for the tab
*
* @param {function} f the function to call when the tab is clicked
*/
Tab.prototype.assignTabClickHandler = function(f) {
var self = this;
self.tab.unbind("click").on("click", function (e) {
// Always close on middle mouse press
if (e.which == 2) {
// Simulate a click on the close tab button so any
// additional on-close behaviour is executed
self.tab.find(".lib_pl_close").click();
return;
}
f();
});
};
/**
* Assign the given function f as the click handler for the tab close button
*
* @param {function} f the function to call when the tab's close button is clicked
*/
Tab.prototype.assignTabCloseClickHandler = function (f) {
this.tab.find(".lib_pl_close").unbind("click").click(f);
};
/**
* Assign the given function f as the click handler for the tab close button
*
* @param {function} f the function to call when the tab's close button is clicked
*/
Tab.prototype.assignTabCloseClickHandler = function(f) {
this.tab.find(".lib_pl_close").unbind("click").click(f);
};
/**
* Assign an implicit destructor
*
* @param {function} fn function to run when this Tab is destroyed
*/
Tab.prototype.assignOnCloseHandler = function (fn) {
this._destroy = fn;
};
/**
* Assign an implicit destructor
*
* @param {function} fn function to run when this Tab is destroyed
*/
Tab.prototype.assignOnCloseHandler = function (fn) {
this._destroy = fn;
};
/**
* Open this tab in the right-hand pane and set it as the currently active tab
*/
Tab.prototype.switchTo = function () {
var self = this;
$activeTab.contents.hide().removeClass("active-tab");
self.contents.addClass("active-tab").show();
/**
* Open this tab in the right-hand pane and set it as the currently active tab
*/
Tab.prototype.switchTo = function() {
var self = this;
$activeTab.contents.hide().removeClass("active-tab");
self.contents.addClass("active-tab").show();
$activeTab.tab.removeClass("active");
self.tab.addClass("active");
$activeTab.tab.removeClass("active");
self.tab.addClass("active");
mod.updateActiveTab();
mod.updateActiveTab();
// In case we're adding a tab that wraps to the next row
// It's better to call this here so we don't have to call it in multiple places
mod.onResize();
return this; // For chaining
};
// In case we're adding a tab that wraps to the next row
// It's better to call this here so we don't have to call it in multiple places
mod.onResize();
return this; // For chaining
};
/**
* Close the tab. Switches to the nearest open tab, prioritizing the
* more recent (rightmost) tabs
*/
Tab.prototype.close = function () {
var self = this;
/**
* Close the tab. Switches to the nearest open tab, prioritizing the
* more recent (rightmost) tabs
*/
Tab.prototype.close = function() {
var self = this;
var ascTabs = Object.keys($openTabs).sort(function (a, b) {
return a - b;
}),
pos = ascTabs.indexOf(self.uid),
toTab =
pos < ascTabs.length - 1
? $openTabs[ascTabs[++pos]]
: $openTabs[ascTabs[--pos]];
delete $openTabs[self.uid]; // Remove this tab from the open tab array
delete $tabMap[self.id]; // Remove this tab from the internal tab mapping
var ascTabs = Object.keys($openTabs).sort(function(a, b){return a-b}),
pos = ascTabs.indexOf(self.uid),
toTab = pos < ascTabs.length-1 ? $openTabs[ascTabs[++pos]] : $openTabs[ascTabs[--pos]];
delete $openTabs[self.uid]; // Remove this tab from the open tab array
delete $tabMap[self.id]; // Remove this tab from the internal tab mapping
// Remove the relevant DOM elements (the tab and its contents)
if (self.uid !== 0) {
self.tab.remove();
self.contents.remove();
} else {
// only hide scheduled shows tab so we can still interact with it.
self.tab.hide();
self.contents.hide();
}
// Remove the relevant DOM elements (the tab and its contents)
if (self.uid !== 0) {
self.tab.remove();
self.contents.remove();
} else {
// only hide scheduled shows tab so we can still interact with it.
self.tab.hide();
self.contents.hide();
}
if (self.isActive() && toTab) {
// Closing the current tab, otherwise we don't need to switch tabs
toTab.switchTo();
} else {
mod.onResize();
}
if (Object.keys($openTabs).length < 1) {
$("#show_builder").hide();
}
if (self.isActive() && toTab) { // Closing the current tab, otherwise we don't need to switch tabs
toTab.switchTo();
} else {
mod.onResize();
}
self._destroy();
};
if (Object.keys($openTabs).length < 1) {
$('#show_builder').hide();
}
/**
* Set the visible Tab name to the given string
*
* @param {string} name the name to set
*/
Tab.prototype.setName = function (name) {
this.tab.find(".tab-name").text(name);
return this; // For chaining
};
self._destroy();
};
/**
* Check if the Tab object is the currently active (open) Tab
*
* @returns {boolean} true if the Tab is the currently active Tab
*/
Tab.prototype.isActive = function () {
return this.contents.get(0) == $activeTab.contents.get(0);
};
/**
* Set the visible Tab name to the given string
*
* @param {string} name the name to set
*/
Tab.prototype.setName = function(name) {
this.tab.find(".tab-name").text(name);
return this; // For chaining
};
/**
* ScheduledTab object constructor
*
* The schedule tab is present in the DOM already on load, and we
* need to be able to reference it in the same way as other tabs
* (to avoid duplication and confusion) so we define it statically
*
* @constructor
*/
var ScheduleTab = function () {
var self = this,
uid = 0,
tab = $("#schedule-tab"),
pane = $("#show_builder"),
contents = pane.find(".outer-datatable-wrapper");
self.id = 0;
self.uid = uid;
/**
* Check if the Tab object is the currently active (open) Tab
*
* @returns {boolean} true if the Tab is the currently active Tab
*/
Tab.prototype.isActive = function() {
return this.contents.get(0) == $activeTab.contents.get(0);
};
tab.data("tab-id", self.id);
/**
* ScheduledTab object constructor
*
* The schedule tab is present in the DOM already on load, and we
* need to be able to reference it in the same way as other tabs
* (to avoid duplication and confusion) so we define it statically
*
* @constructor
*/
var ScheduleTab = function() {
var self = this, uid = 0,
tab = $("#schedule-tab"),
pane = $("#show_builder"),
contents = pane.find(".outer-datatable-wrapper");
self.id = 0;
self.uid = uid;
self.wrapper = pane;
self.contents = contents;
self.tab = tab;
tab.data("tab-id", self.id);
self.assignTabClickHandler(function (e) {
if (!self.isActive()) {
self.switchTo();
}
});
self.wrapper = pane;
self.contents = contents;
self.tab = tab;
self.assignTabCloseClickHandler(function (e) {
self.close();
});
self.assignTabClickHandler(function(e) {
if (!self.isActive()) {
self.switchTo();
}
});
$openTabs[uid] = self;
$tabMap[self.id] = uid;
};
/**
* Subclass the Tab object
* @type {Tab}
*/
ScheduleTab.prototype = Object.create(Tab.prototype);
ScheduleTab.prototype.constructor = ScheduleTab;
self.assignTabCloseClickHandler(function(e) {
self.close();
});
$openTabs[uid] = self;
$tabMap[self.id] = uid;
};
/**
* Subclass the Tab object
* @type {Tab}
*/
ScheduleTab.prototype = Object.create(Tab.prototype);
ScheduleTab.prototype.constructor = ScheduleTab;
/* #####################################################
/* #####################################################
Module Functions
##################################################### */
/**
* Initialize the singleton ScheduleTab object on startup
*/
mod.initScheduleTab = function() {
$scheduleTab = new ScheduleTab();
$activeTab = $scheduleTab;
};
/**
* Initialize the singleton ScheduleTab object on startup
*/
mod.initScheduleTab = function () {
$scheduleTab = new ScheduleTab();
$activeTab = $scheduleTab;
};
/**
* Create a new Tab object and open it in the ShowBuilder pane
*
* @param {string} html the HTML to render as the tab contents
* @param {string} uid the unique ID for the tab. Uses the values in
* AIRTIME.library.MediaTypeStringEnum and the object ID
* @param {function} callback an optional callback function to call once the
* Tab object is initialized
* @returns {Tab} the created Tab object
*/
mod.openTab = function(html, uid, callback) {
$('#show_builder').show();
var newTab = new Tab(html, uid);
if (callback) callback(newTab);
return newTab;
};
/**
* Create a new Tab object and open it in the ShowBuilder pane
*
* @param {string} html the HTML to render as the tab contents
* @param {string} uid the unique ID for the tab. Uses the values in
* AIRTIME.library.MediaTypeStringEnum and the object ID
* @param {function} callback an optional callback function to call once the
* Tab object is initialized
* @returns {Tab} the created Tab object
*/
mod.openTab = function (html, uid, callback) {
$("#show_builder").show();
var newTab = new Tab(html, uid);
if (callback) callback(newTab);
return newTab;
};
/**
* open the schedule tab if if was closed
*
* @returns {Tab}
*/
mod.openScheduleTab = function() {
var $scheduleTab = this.getScheduleTab();
$('#show_builder').show();
$openTabs[0] = $scheduleTab;
$scheduleTab.tab.show();
$scheduleTab.contents.show();
$scheduleTab.switchTo();
$scheduleTab.assignTabCloseClickHandler(function(e) {
$scheduleTab.close();
});
};
/**
* Updates the currently active tab
*
* Called when the user switches tabs for any reason
*
* NOTE: this function updates the currently active playlist
* as a side-effect, which is necessary for playlist tabs
* but not for other types of tabs... would be good to
* get rid of this dependency at some point
*/
mod.updateActiveTab = function() {
var t = $(".nav.nav-tabs .active");
$activeTab = mod.get(t.data("tab-id"));
if (!$activeTab) $activeTab = $scheduleTab;
if ($activeTab.contents.hasClass("pl-content")) {
AIRTIME.playlist.setCurrent($activeTab.contents);
}
};
/**
* Get the ScheduleTab object
*
* @returns {ScheduleTab}
*/
mod.getScheduleTab = function() {
return $scheduleTab;
};
/**
* Get the currently active (open) Tab object
*
* @returns {Tab} the currently active tab
*/
mod.getActiveTab = function() {
return $activeTab;
};
/**
* Given a tab id, get the corresponding Tab object
*
* @param {int|string} id the tab or object ID of the Tab to retrieve
* @returns {Tab|undefined} the Tab object with the given ID, or undefined
* if no Tab with the given ID exists
*/
mod.get = function(id) {
return $.isNumeric(id) ? $openTabs[$tabMap[id]] : $openTabs[id];
};
/**
* Adjust the margins on the right-hand pane when we have multiple rows of tabs
*/
mod.onResize = function() {
var h = $(".panel-header .nav").height();
$(".pl-content").css("margin-top", h + 5); // 8px extra for padding
$("#show_builder_table_wrapper").css("top", h + 5);
};
/**
* Expose the Tab object so it can be subclassed
*
* @type {Function}
*/
mod.Tab = Tab;
return AIRTIME;
}(AIRTIME || {}));
$(document).ready(function() {
var sb = $("#show_builder");
// Add text scrolling to tab names
sb.addTitles(".tab-name");
sb.find(".nav.nav-tabs").sortable({
containment: "parent",
distance: 25
/**
* open the schedule tab if if was closed
*
* @returns {Tab}
*/
mod.openScheduleTab = function () {
var $scheduleTab = this.getScheduleTab();
$("#show_builder").show();
$openTabs[0] = $scheduleTab;
$scheduleTab.tab.show();
$scheduleTab.contents.show();
$scheduleTab.switchTo();
$scheduleTab.assignTabCloseClickHandler(function (e) {
$scheduleTab.close();
});
// Initialize the ScheduleTab
AIRTIME.tabs.initScheduleTab();
};
/**
* Updates the currently active tab
*
* Called when the user switches tabs for any reason
*
* NOTE: this function updates the currently active playlist
* as a side-effect, which is necessary for playlist tabs
* but not for other types of tabs... would be good to
* get rid of this dependency at some point
*/
mod.updateActiveTab = function () {
var t = $(".nav.nav-tabs .active");
$activeTab = mod.get(t.data("tab-id"));
if (!$activeTab) $activeTab = $scheduleTab;
if ($activeTab.contents.hasClass("pl-content")) {
AIRTIME.playlist.setCurrent($activeTab.contents);
}
};
/**
* Get the ScheduleTab object
*
* @returns {ScheduleTab}
*/
mod.getScheduleTab = function () {
return $scheduleTab;
};
/**
* Get the currently active (open) Tab object
*
* @returns {Tab} the currently active tab
*/
mod.getActiveTab = function () {
return $activeTab;
};
/**
* Given a tab id, get the corresponding Tab object
*
* @param {int|string} id the tab or object ID of the Tab to retrieve
* @returns {Tab|undefined} the Tab object with the given ID, or undefined
* if no Tab with the given ID exists
*/
mod.get = function (id) {
return $.isNumeric(id) ? $openTabs[$tabMap[id]] : $openTabs[id];
};
/**
* Adjust the margins on the right-hand pane when we have multiple rows of tabs
*/
mod.onResize = function () {
var h = $(".panel-header .nav").height();
$(".pl-content").css("margin-top", h + 5); // 8px extra for padding
$("#show_builder_table_wrapper").css("top", h + 5);
};
/**
* Expose the Tab object so it can be subclassed
*
* @type {Function}
*/
mod.Tab = Tab;
return AIRTIME;
})(AIRTIME || {});
$(document).ready(function () {
var sb = $("#show_builder");
// Add text scrolling to tab names
sb.addTitles(".tab-name");
sb.find(".nav.nav-tabs").sortable({
containment: "parent",
distance: 25,
});
// Initialize the ScheduleTab
AIRTIME.tabs.initScheduleTab();
});
$(window).resize(AIRTIME.tabs.onResize);