Merge branch 'saas-dev-publishing' of github.com:sourcefabric/Airtime into saas-dev-publishing
Conflicts: airtime_mvc/public/js/airtime/library/podcast.js
This commit is contained in:
commit
3790b0fa81
|
@ -378,7 +378,6 @@ class LibraryController extends Zend_Controller_Action
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
$this->view->id = $file_id;
|
$this->view->id = $file_id;
|
||||||
$this->view->title = $file->getPropelOrm()->getDbTrackTitle();
|
$this->view->title = $file->getPropelOrm()->getDbTrackTitle();
|
||||||
$this->view->type = "md";
|
|
||||||
$this->view->html = $this->view->render('library/edit-file-md.phtml');
|
$this->view->html = $this->view->render('library/edit-file-md.phtml');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ var AIRTIME = (function(AIRTIME) {
|
||||||
openTabObjectIds.each(function(i, el) {
|
openTabObjectIds.each(function(i, el) {
|
||||||
var v = parseInt($(el).val());
|
var v = parseInt($(el).val());
|
||||||
if ($.inArray(v, mediaIds) > -1) {
|
if ($.inArray(v, mediaIds) > -1) {
|
||||||
AIRTIME.tabs.closeTab($(el).closest(".pl-content").attr("data-tab-id"));
|
AIRTIME.tabs.get($(el).closest(".pl-content").attr("data-tab-id")).close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,13 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
|
|
||||||
//AngularJS app
|
//AngularJS app
|
||||||
var podcastApp = angular.module('podcast', [])
|
var podcastApp = angular.module('podcast', [])
|
||||||
.controller('RestController', function($scope, $http, podcast) {
|
.controller('RestController', function($scope, $http, podcast, tab) {
|
||||||
|
|
||||||
//We take a podcast object in as a parameter rather fetching the podcast by ID here because
|
//We take a podcast object in as a parameter rather fetching the podcast by ID here because
|
||||||
//when you're creating a new podcast, we already have the object from the result of the POST. We're saving
|
//when you're creating a new podcast, we already have the object from the result of the POST. We're saving
|
||||||
//a roundtrip by not fetching it again here.
|
//a roundtrip by not fetching it again here.
|
||||||
$scope.podcast = podcast;
|
$scope.podcast = podcast;
|
||||||
AIRTIME.tabs.setActiveTabName($scope.podcast.title);
|
tab.setName($scope.podcast.title);
|
||||||
|
|
||||||
$scope.savePodcast = function() {
|
$scope.savePodcast = function() {
|
||||||
$http.put(endpoint + $scope.podcast.id, { csrf_token: jQuery("#csrf").val(), podcast: $scope.podcast })
|
$http.put(endpoint + $scope.podcast.id, { csrf_token: jQuery("#csrf").val(), podcast: $scope.podcast })
|
||||||
|
@ -29,7 +29,7 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.discard = function() {
|
$scope.discard = function() {
|
||||||
AIRTIME.tabs.getActiveTab().close();
|
tab.close();
|
||||||
$scope.podcast = {};
|
$scope.podcast = {};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -46,9 +46,10 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
$.post(endpoint + "bulk", { csrf_token: $("#csrf").val(), method: method, ids: ids }, callback);
|
$.post(endpoint + "bulk", { csrf_token: $("#csrf").val(), method: method, ids: ids }, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _bootstrapAngularApp(podcast) {
|
function _bootstrapAngularApp(podcast, tab) {
|
||||||
podcastApp.value('podcast', JSON.parse(podcast));
|
podcastApp.value('podcast', JSON.parse(podcast));
|
||||||
var wrapper = AIRTIME.tabs.getActiveTab().contents.find(".editor_pane_wrapper");
|
podcastApp.value('tab', tab);
|
||||||
|
var wrapper = tab.contents.find(".editor_pane_wrapper");
|
||||||
wrapper.attr("ng-controller", "RestController");
|
wrapper.attr("ng-controller", "RestController");
|
||||||
angular.bootstrap(wrapper.get(0), ["podcast"]);
|
angular.bootstrap(wrapper.get(0), ["podcast"]);
|
||||||
}
|
}
|
||||||
|
@ -68,11 +69,10 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
|
|
||||||
mod.addPodcast = function() {
|
mod.addPodcast = function() {
|
||||||
$.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) {
|
$.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) {
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+json.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+json.id,
|
||||||
AIRTIME.tabs.openTab(json, uid);
|
tab = AIRTIME.tabs.openTab(json, uid);
|
||||||
_bootstrapAngularApp(json.podcast);
|
_bootstrapAngularApp(json.podcast, tab);
|
||||||
$("#podcast_url_dialog").dialog("close");
|
$("#podcast_url_dialog").dialog("close");
|
||||||
console.log(json);
|
|
||||||
mod.initPodcastEpisodeDatatable(JSON.parse(json.podcast).episodes);
|
mod.initPodcastEpisodeDatatable(JSON.parse(json.podcast).episodes);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -80,9 +80,9 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
mod.editSelectedPodcasts = function() {
|
mod.editSelectedPodcasts = function() {
|
||||||
_bulkAction("GET", function(json) {
|
_bulkAction("GET", function(json) {
|
||||||
json.forEach(function(el) {
|
json.forEach(function(el) {
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+el.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+el.id,
|
||||||
AIRTIME.tabs.openTab(el, uid, AIRTIME.podcast.init);
|
tab = AIRTIME.tabs.openTab(el, uid, AIRTIME.podcast.init);
|
||||||
_bootstrapAngularApp(el.podcast);
|
_bootstrapAngularApp(el.podcast, tab);
|
||||||
mod.initPodcastEpisodeDatatable(JSON.parse(el.podcast).episodes);
|
mod.initPodcastEpisodeDatatable(JSON.parse(el.podcast).episodes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -97,7 +97,6 @@ var AIRTIME = (function (AIRTIME) {
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.initPodcastEpisodeDatatable = function(episodes) {
|
mod.initPodcastEpisodeDatatable = function(episodes) {
|
||||||
console.log(episodes);
|
|
||||||
var aoColumns = [
|
var aoColumns = [
|
||||||
/* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" },
|
/* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" },
|
||||||
/* Author */ { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" },
|
/* Author */ { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" },
|
||||||
|
|
|
@ -381,7 +381,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
setCueEvents();
|
setCueEvents();
|
||||||
setFadeEvents();
|
setFadeEvents();
|
||||||
mod.setModified(json.modified);
|
mod.setModified(json.modified);
|
||||||
AIRTIME.tabs.setActiveTabName(json.name);
|
AIRTIME.tabs.getActiveTab().setName(json.name);
|
||||||
|
|
||||||
AIRTIME.playlist.validatePlaylistElements();
|
AIRTIME.playlist.validatePlaylistElements();
|
||||||
redrawLib();
|
redrawLib();
|
||||||
|
@ -788,7 +788,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
setTimeout(function(){$status.fadeOut("slow", function(){$status.empty()})}, 5000);
|
setTimeout(function(){$status.fadeOut("slow", function(){$status.empty()})}, 5000);
|
||||||
|
|
||||||
$pl.find(".title_obj_name").val(name);
|
$pl.find(".title_obj_name").val(name);
|
||||||
AIRTIME.tabs.setActiveTabName(name);
|
AIRTIME.tabs.getActiveTab().setName(json.name);
|
||||||
|
|
||||||
var $ws_id = $(".active-tab .obj_id");
|
var $ws_id = $(".active-tab .obj_id");
|
||||||
$ws_id.attr("value", json.streamId);
|
$ws_id.attr("value", json.streamId);
|
||||||
|
@ -889,7 +889,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
setTitleLabel(json.name);
|
setTitleLabel(json.name);
|
||||||
AIRTIME.tabs.setActiveTabName(json.name);
|
AIRTIME.tabs.getActiveTab().setName(json.name);
|
||||||
mod.setModified(json.modified);
|
mod.setModified(json.modified);
|
||||||
|
|
||||||
if (obj_type == "block") {
|
if (obj_type == "block") {
|
||||||
|
@ -1016,6 +1016,56 @@ var AIRTIME = (function(AIRTIME){
|
||||||
AIRTIME.playlist.validatePlaylistElements();
|
AIRTIME.playlist.validatePlaylistElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod._initPlaylistTabEvents = function(newTab) {
|
||||||
|
newTab.assignTabClickHandler(function() {
|
||||||
|
if (!$(this).hasClass('active')) {
|
||||||
|
newTab.switchTo();
|
||||||
|
$.post(baseUrl+'playlist/edit', {
|
||||||
|
format: "json",
|
||||||
|
id: newTab.pane.find(".obj_id").val(),
|
||||||
|
type: newTab.pane.find(".obj_type").val()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mod.init();
|
||||||
|
|
||||||
|
// functions in smart_blockbuilder.js
|
||||||
|
setupUI();
|
||||||
|
appendAddButton();
|
||||||
|
appendModAddButton();
|
||||||
|
removeButtonCheck();
|
||||||
|
mod.setFadeIcon();
|
||||||
|
};
|
||||||
|
|
||||||
|
mod._initFileMdEvents = function(newTab) {
|
||||||
|
newTab.contents.find(".md-cancel").on("click", function() {
|
||||||
|
newTab.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
newTab.contents.find(".md-save").on("click", function() {
|
||||||
|
var file_id = newTab.wrapper.find('#file_id').val(),
|
||||||
|
data = newTab.wrapper.find("#edit-md-dialog form").serializeArray();
|
||||||
|
$.post(baseUrl+'library/edit-file-md', {format: "json", id: file_id, 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.wrapper.find('#edit-md-dialog').on("keyup", function(event) {
|
||||||
|
if (event.keyCode === 13) {
|
||||||
|
newTab.wrapper.find('.md-save').click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mod.setupEventListeners();
|
||||||
|
};
|
||||||
|
|
||||||
mod.fnNew = function() {
|
mod.fnNew = function() {
|
||||||
var url = baseUrl+'playlist/new';
|
var url = baseUrl+'playlist/new';
|
||||||
|
|
||||||
|
@ -1025,7 +1075,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
{format: "json", type: 'playlist'},
|
{format: "json", type: 'playlist'},
|
||||||
function(json) {
|
function(json) {
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.PLAYLIST+"_"+json.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.PLAYLIST+"_"+json.id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
redrawLib();
|
redrawLib();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1039,7 +1089,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
{format: "json"},
|
{format: "json"},
|
||||||
function(json) {
|
function(json) {
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM+"_"+json.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM+"_"+json.id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
redrawLib();
|
redrawLib();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1054,13 +1104,13 @@ var AIRTIME = (function(AIRTIME){
|
||||||
{format: "json", type: 'block'},
|
{format: "json", type: 'block'},
|
||||||
function(json){
|
function(json){
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK+"_"+json.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK+"_"+json.id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
redrawLib();
|
redrawLib();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.fileMdEdit = function(json, uid) {
|
mod.fileMdEdit = function(json, uid) {
|
||||||
AIRTIME.tabs.openFileMdEditorTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initFileMdEvents);
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.fnEdit = function(id, type, url) {
|
mod.fnEdit = function(id, type, url) {
|
||||||
|
@ -1071,7 +1121,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
{format: "json", id: id, type: type},
|
{format: "json", id: id, type: type},
|
||||||
function(json) {
|
function(json) {
|
||||||
var uid = AIRTIME.library.MediaTypeFullToStringEnum.type+"_"+id;
|
var uid = AIRTIME.library.MediaTypeFullToStringEnum.type+"_"+id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
redrawLib();
|
redrawLib();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1107,7 +1157,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
{format: "json", ids: id, modified: lastMod, type: type},
|
{format: "json", ids: id, modified: lastMod, type: type},
|
||||||
function(json){
|
function(json){
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM+"_"+id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.WEBSTREAM+"_"+id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
redrawLib();
|
redrawLib();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1155,7 +1205,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
mod.replaceForm = function(json){
|
mod.replaceForm = function(json){
|
||||||
$pl.find('.editor_pane_wrapper').html(json.html);
|
$pl.find('.editor_pane_wrapper').html(json.html);
|
||||||
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK+"_"+json.id;
|
var uid = AIRTIME.library.MediaTypeStringEnum.BLOCK+"_"+json.id;
|
||||||
AIRTIME.tabs.openPlaylistTab(json, uid);
|
AIRTIME.tabs.openTab(json, uid, AIRTIME.playlist._initPlaylistTabEvents);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1432,6 +1482,10 @@ var AIRTIME = (function(AIRTIME){
|
||||||
|
|
||||||
mod.setCurrent = function(pl) {
|
mod.setCurrent = function(pl) {
|
||||||
$pl = pl;
|
$pl = pl;
|
||||||
|
$.post(baseUrl + "playlist/change-playlist", {
|
||||||
|
"id": mod.getId($pl),
|
||||||
|
"type": $pl.find('.obj_type').val()
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.init = function() {
|
mod.init = function() {
|
||||||
|
@ -1485,16 +1539,8 @@ var AIRTIME = (function(AIRTIME){
|
||||||
AIRTIME.playlist.init();
|
AIRTIME.playlist.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
return AIRTIME;
|
return AIRTIME;
|
||||||
|
|
||||||
}(AIRTIME || {}));
|
}(AIRTIME || {}));
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(AIRTIME.playlist.onReady);
|
$(document).ready(AIRTIME.playlist.onReady);
|
||||||
$(window).resize(AIRTIME.playlist.onResize);
|
|
||||||
|
|
|
@ -1,9 +1,40 @@
|
||||||
var AIRTIME = (function(AIRTIME){
|
var AIRTIME = (function(AIRTIME){
|
||||||
|
/**
|
||||||
|
* AIRTIME module namespace object
|
||||||
|
*/
|
||||||
var mod,
|
var mod,
|
||||||
|
/**
|
||||||
|
* Tab counter to use as unique tab IDs that can be
|
||||||
|
* retrieved from the DOM
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
$tabCount = 0,
|
$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 = {},
|
$tabMap = {},
|
||||||
|
/**
|
||||||
|
* Map of object UIDs to currently open Tab objects
|
||||||
|
*
|
||||||
|
* @type {{}}
|
||||||
|
*/
|
||||||
$openTabs = {},
|
$openTabs = {},
|
||||||
|
/**
|
||||||
|
* The currently active (open) Tab object
|
||||||
|
*
|
||||||
|
* @type {Tab}
|
||||||
|
*/
|
||||||
$activeTab,
|
$activeTab,
|
||||||
|
/**
|
||||||
|
* Singleton object used to reference the schedule tab
|
||||||
|
*
|
||||||
|
* @type {ScheduleTab}
|
||||||
|
*/
|
||||||
$scheduleTab;
|
$scheduleTab;
|
||||||
|
|
||||||
if (AIRTIME.tabs === undefined) {
|
if (AIRTIME.tabs === undefined) {
|
||||||
|
@ -12,9 +43,22 @@ var AIRTIME = (function(AIRTIME){
|
||||||
mod = AIRTIME.tabs;
|
mod = AIRTIME.tabs;
|
||||||
|
|
||||||
/* #####################################################
|
/* #####################################################
|
||||||
Internal Functions
|
Object Initialization and Functions
|
||||||
##################################################### */
|
##################################################### */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab object constructor
|
||||||
|
*
|
||||||
|
* @param {{}} json a javascript object of the form
|
||||||
|
* {
|
||||||
|
* '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(json, uid) {
|
var Tab = function(json, uid) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -28,17 +72,18 @@ var AIRTIME = (function(AIRTIME){
|
||||||
self.id = ++$tabCount;
|
self.id = ++$tabCount;
|
||||||
self.uid = uid;
|
self.uid = uid;
|
||||||
|
|
||||||
var wrapper = "<div data-tab-type='" + json.type + "' data-tab-id='" + self.id + "' id='pl-tab-content-" + self.id + "' class='side_playlist pl-content'><div class='editor_pane_wrapper'></div></div>",
|
// 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),
|
t = $("#show_builder").append(wrapper).find("#pl-tab-content-" + self.id),
|
||||||
pane = $(".editor_pane_wrapper:last").append(json.html),
|
pane = $(".editor_pane_wrapper:last").append(json.html),
|
||||||
name = pane.find("#track_title").length > 0 ? pane.find("#track_title").val() + $.i18n._(" - Metadata Editor")
|
name = pane.find("#track_title").length > 0 ? pane.find("#track_title").val() + $.i18n._(" - Metadata Editor")
|
||||||
: pane.find(".playlist_name_display").val(),
|
: pane.find(".playlist_name_display").val(),
|
||||||
tab =
|
tab =
|
||||||
"<li data-tab-id='" + self.id + "' data-tab-type='" + json.type + "' id='pl-tab-" + self.id + "' role='presentation' class='active'>" +
|
"<li data-tab-id='" + self.id + "' id='pl-tab-" + self.id + "' role='presentation' class='active'>" +
|
||||||
"<a href='javascript:void(0)'>" +
|
"<a href='javascript:void(0)'>" +
|
||||||
"<span class='tab-name'>" + name + "</span>" +
|
"<span class='tab-name'>" + name + "</span>" +
|
||||||
"<span href='#' class='lib_pl_close icon-remove'></span>" +
|
"<span href='#' class='lib_pl_close icon-remove'></span>" +
|
||||||
"</a>" +
|
"</a>" +
|
||||||
"</li>",
|
"</li>",
|
||||||
tabs = $(".nav.nav-tabs");
|
tabs = $(".nav.nav-tabs");
|
||||||
|
|
||||||
|
@ -54,47 +99,18 @@ var AIRTIME = (function(AIRTIME){
|
||||||
$openTabs[uid] = self;
|
$openTabs[uid] = self;
|
||||||
$tabMap[self.id] = uid;
|
$tabMap[self.id] = uid;
|
||||||
|
|
||||||
|
self._init();
|
||||||
self.switchTo();
|
self.switchTo();
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
||||||
|
|
||||||
Tab.prototype.switchTo = function() {
|
/**
|
||||||
_switchTab(this.contents, this.tab);
|
* Private initialization function for Tab objects
|
||||||
};
|
*
|
||||||
|
* Assigns default action handlers to the tab DOM element
|
||||||
Tab.prototype.close = function() {
|
*
|
||||||
var self = this;
|
* @private
|
||||||
|
*/
|
||||||
var toPane = self.contents.next().length > 0 ? self.contents.next() : self.contents.prev(),
|
|
||||||
toTab = self.tab.next().length > 0 ? self.tab.next() : self.tab.prev();
|
|
||||||
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)
|
|
||||||
self.tab.remove();
|
|
||||||
self.contents.remove();
|
|
||||||
|
|
||||||
if (self.isActive()) { // Closing the current tab, otherwise we don't need to switch tabs
|
|
||||||
_switchTab(toPane, toTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we close a tab that was causing tabs to wrap to the next row
|
|
||||||
// we need to resize to change the margin for the tab nav
|
|
||||||
AIRTIME.playlist.onResize();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Tab.prototype.isActive = function() {
|
|
||||||
return this.contents.get(0) == $activeTab.contents.get(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
Tab.prototype.assignTabClickHandler = function(f) {
|
|
||||||
this.tab.unbind("click").on("click", f);
|
|
||||||
};
|
|
||||||
Tab.prototype.assignTabCloseClickHandler = function(f) {
|
|
||||||
this.tab.find(".lib_pl_close").unbind("click").click(f);
|
|
||||||
};
|
|
||||||
|
|
||||||
Tab.prototype._init = function() {
|
Tab.prototype._init = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.assignTabClickHandler(function() {
|
self.assignTabClickHandler(function() {
|
||||||
|
@ -116,6 +132,92 @@ var AIRTIME = (function(AIRTIME){
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
this.tab.unbind("click").on("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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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");
|
||||||
|
|
||||||
|
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();
|
||||||
|
AIRTIME.library.fnRedraw();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// Remove the relevant DOM elements (the tab and its contents)
|
||||||
|
self.tab.remove();
|
||||||
|
self.contents.remove();
|
||||||
|
|
||||||
|
if (self.isActive()) { // Closing the current tab, otherwise we don't need to switch tabs
|
||||||
|
toTab.switchTo();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ScheduleTab = function() {
|
||||||
var self = this, uid = 0,
|
var self = this, uid = 0,
|
||||||
tab = $("#schedule-tab"),
|
tab = $("#schedule-tab"),
|
||||||
|
@ -124,143 +226,113 @@ var AIRTIME = (function(AIRTIME){
|
||||||
self.id = 0;
|
self.id = 0;
|
||||||
|
|
||||||
tab.data("tab-id", self.id);
|
tab.data("tab-id", self.id);
|
||||||
tab.on("click", function() {
|
|
||||||
if (!$(this).hasClass('active')) {
|
|
||||||
_switchTab(contents, $(this));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.wrapper = pane;
|
self.wrapper = pane;
|
||||||
self.contents = contents;
|
self.contents = contents;
|
||||||
self.tab = tab;
|
self.tab = tab;
|
||||||
|
|
||||||
|
tab.on("click", function() {
|
||||||
|
if (!$(this).hasClass('active')) {
|
||||||
|
self.switchTo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$openTabs[uid] = self;
|
$openTabs[uid] = self;
|
||||||
$tabMap[self.id] = uid;
|
$tabMap[self.id] = uid;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Subclass the Tab object
|
||||||
|
* @type {Tab}
|
||||||
|
*/
|
||||||
ScheduleTab.prototype = Object.create(Tab.prototype);
|
ScheduleTab.prototype = Object.create(Tab.prototype);
|
||||||
ScheduleTab.prototype.constructor = ScheduleTab;
|
ScheduleTab.prototype.constructor = ScheduleTab;
|
||||||
|
|
||||||
function _initFileMdEvents(newTab) {
|
|
||||||
newTab.contents.find(".md-cancel").on("click", function() {
|
|
||||||
newTab.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
newTab.contents.find(".md-save").on("click", function() {
|
|
||||||
var file_id = newTab.wrapper.find('#file_id').val(),
|
|
||||||
data = newTab.wrapper.find("#edit-md-dialog form").serializeArray();
|
|
||||||
$.post(baseUrl+'library/edit-file-md', {format: "json", id: file_id, 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.wrapper.find('#edit-md-dialog').on("keyup", function(event) {
|
|
||||||
if (event.keyCode === 13) {
|
|
||||||
newTab.wrapper.find('.md-save').click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AIRTIME.playlist.setupEventListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _initPlaylistEvents(newTab) {
|
|
||||||
newTab.assignTabClickHandler(function() {
|
|
||||||
if (!$(this).hasClass('active')) {
|
|
||||||
newTab.switchTo();
|
|
||||||
$.post(baseUrl+'playlist/edit', {
|
|
||||||
format: "json",
|
|
||||||
id: newTab.pane.find(".obj_id").val(),
|
|
||||||
type: newTab.pane.find(".obj_type").val()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AIRTIME.playlist.init();
|
|
||||||
|
|
||||||
// functions in smart_blockbuilder.js
|
|
||||||
setupUI();
|
|
||||||
appendAddButton();
|
|
||||||
appendModAddButton();
|
|
||||||
removeButtonCheck();
|
|
||||||
AIRTIME.playlist.setFadeIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _switchTab(tabPane, tab) {
|
|
||||||
$activeTab.contents.hide().removeClass("active-tab");
|
|
||||||
tabPane.addClass("active-tab").show();
|
|
||||||
|
|
||||||
$activeTab.tab.removeClass("active");
|
|
||||||
tab.addClass("active");
|
|
||||||
|
|
||||||
mod.updateActiveTab();
|
|
||||||
|
|
||||||
AIRTIME.playlist.onResize();
|
|
||||||
AIRTIME.library.fnRedraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #####################################################
|
/* #####################################################
|
||||||
External Functions
|
External Functions
|
||||||
##################################################### */
|
##################################################### */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the singleton ScheduleTab object on startup
|
||||||
|
*/
|
||||||
mod.init = function() {
|
mod.init = function() {
|
||||||
$scheduleTab = new ScheduleTab();
|
$scheduleTab = Object.freeze(new ScheduleTab());
|
||||||
};
|
|
||||||
|
|
||||||
mod.openFileMdEditorTab = function(json, uid) {
|
|
||||||
mod.openTab(json, uid, _initFileMdEvents);
|
|
||||||
};
|
|
||||||
|
|
||||||
mod.openPlaylistTab = function(json, uid) {
|
|
||||||
mod.openTab(json, uid, _initPlaylistEvents);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Tab object and open it in the ShowBuilder pane
|
||||||
|
*
|
||||||
|
* @param {{}} json a javascript object of the form
|
||||||
|
* {
|
||||||
|
* '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(json, uid, callback) {
|
mod.openTab = function(json, uid, callback) {
|
||||||
var newTab = new Tab(json, uid);
|
var newTab = new Tab(json, uid);
|
||||||
newTab._init();
|
|
||||||
if (callback) callback(newTab);
|
if (callback) callback(newTab);
|
||||||
|
return newTab;
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.closeTab = function(id) {
|
/**
|
||||||
$openTabs[$tabMap[id]].close();
|
* Updates the currently active tab
|
||||||
};
|
*
|
||||||
|
* Called when the user switches tabs for any reason
|
||||||
mod.setActiveTabName = function(name) {
|
*
|
||||||
$activeTab.tab.find(".tab-name").text(name);
|
* 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() {
|
mod.updateActiveTab = function() {
|
||||||
var t = $(".nav.nav-tabs .active");
|
var t = $(".nav.nav-tabs .active");
|
||||||
$activeTab = mod.get(t.data("tab-id"));
|
$activeTab = mod.get(t.data("tab-id"));
|
||||||
if ($activeTab.contents.hasClass("pl-content")) {
|
if ($activeTab.contents.hasClass("pl-content")) {
|
||||||
mod.updatePlaylist();
|
AIRTIME.playlist.setCurrent($activeTab.contents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mod.updatePlaylist = function() {
|
/**
|
||||||
AIRTIME.playlist.setCurrent($activeTab.contents);
|
* Get the ScheduleTab object
|
||||||
$.post(baseUrl + "playlist/change-playlist", {
|
*
|
||||||
"id": AIRTIME.playlist.getId($activeTab.contents),
|
* @returns {ScheduleTab}
|
||||||
"type": $activeTab.contents.find('.obj_type').val()
|
*/
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
mod.getScheduleTab = function() {
|
mod.getScheduleTab = function() {
|
||||||
return $scheduleTab;
|
return $scheduleTab;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently active (open) Tab object
|
||||||
|
*
|
||||||
|
* @returns {Tab} the currently active tab
|
||||||
|
*/
|
||||||
mod.getActiveTab = function() {
|
mod.getActiveTab = function() {
|
||||||
return $activeTab;
|
return $activeTab;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a tab id, get the corresponding Tab object
|
||||||
|
*
|
||||||
|
* @param {int} id the tab 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) {
|
mod.get = function(id) {
|
||||||
return $openTabs[$tabMap[id]];
|
return $openTabs[$tabMap[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);
|
||||||
|
};
|
||||||
|
|
||||||
return AIRTIME;
|
return AIRTIME;
|
||||||
|
|
||||||
}(AIRTIME || {}));
|
}(AIRTIME || {}));
|
||||||
|
@ -268,4 +340,5 @@ var AIRTIME = (function(AIRTIME){
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$("#show_builder").textScroll(".tab-name");
|
$("#show_builder").textScroll(".tab-name");
|
||||||
AIRTIME.tabs.init();
|
AIRTIME.tabs.init();
|
||||||
});
|
});
|
||||||
|
$(window).resize(AIRTIME.tabs.onResize);
|
||||||
|
|
Loading…
Reference in New Issue