diff --git a/airtime_mvc/application/views/scripts/podcast/podcast.phtml b/airtime_mvc/application/views/scripts/podcast/podcast.phtml index 2a2c8122e..9342636f2 100644 --- a/airtime_mvc/application/views/scripts/podcast/podcast.phtml +++ b/airtime_mvc/application/views/scripts/podcast/podcast.phtml @@ -41,7 +41,7 @@ - +
diff --git a/airtime_mvc/application/views/scripts/showbuilder/index.phtml b/airtime_mvc/application/views/scripts/showbuilder/index.phtml index 9a8a4316d..b5093d583 100644 --- a/airtime_mvc/application/views/scripts/showbuilder/index.phtml +++ b/airtime_mvc/application/views/scripts/showbuilder/index.phtml @@ -16,7 +16,6 @@
-
diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 1939b1fd2..dc733b78f 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -92,7 +92,6 @@ var AIRTIME = (function(AIRTIME) { mod.DataTableTypeEnum = Object.freeze({ LIBRARY : "library", PODCAST : "podcast", - PODCAST_EPISODES: "podcastEpisodes" }); // TODO: once the new manual pages are added, change links! @@ -480,7 +479,7 @@ var AIRTIME = (function(AIRTIME) { oTable.fnStandingRedraw(); }; - mod.fnDeleteItems = function(aMedia) { + mod.fnDeleteItems = function(aMedia, podcastId) { //Prevent the user from spamming the delete button while the AJAX request is in progress AIRTIME.button.disableButton("btn-group #sb-delete", false); var openTabObjectIds = $(".obj_id"), @@ -504,10 +503,12 @@ var AIRTIME = (function(AIRTIME) { } chosenItems = {}; - if (oTable == $datatables[mod.DataTableTypeEnum.PODCAST_EPISODES]) { - mod.podcastEpisodeTableWidget.reload(); - } else { + + if (typeof(podcastId) === "undefined") { oTable.fnStandingRedraw(); + } else { + AIRTIME.podcast.episodeTables[podcastId].reload(this.podcast_id); + AIRTIME.podcast.episodeTables[podcastId].clearSelection(); } //Re-enable the delete button @@ -1330,8 +1331,8 @@ var AIRTIME = (function(AIRTIME) { return oTable; }; - mod.openPodcastEpisodeDialog = function () { - var episode = mod.podcastEpisodeTableWidget.getSelectedRows()[0]; + mod.openPodcastEpisodeDialog = function (podcastId) { + var episode = AIRTIME.podcast.episodeTables[podcastId].getSelectedRows()[0]; $("body").append("
"); var dialog = $("#podcast_episode_dialog").html(episode.description); dialog.html(dialog.text()); @@ -1399,31 +1400,6 @@ var AIRTIME = (function(AIRTIME) { } }); - var openPodcastEpisodeTable = function (podcast) { - $("#library_filter").append(" - " + podcast.title); - mod.podcastEpisodeTableWidget.reload(podcast.id); - mod.podcastTableWidget.clearSelection(); - mod.setCurrentTable(mod.DataTableTypeEnum.PODCAST_EPISODES); - mod.podcastEpisodeDataTable.closest(".dataTables_wrapper").find(".dataTables_processing") - .addClass("block-overlay").css("visibility", "visible"); - }; - - podcastToolbarButtons["ViewEpisodes"] = { - title : $.i18n._("View Episodes"), - iconClass : "icon-chevron-right", - extraBtnClass : "btn-small", - elementId : "", - eventHandlers : { - click: function () { - var podcast = mod.podcastTableWidget.getSelectedRows()[0]; - openPodcastEpisodeTable(podcast); - } - }, - validateConstraints: function () { - return this.getSelectedRows().length == 1; - } - }; - //Set up the div with id "podcast_table" as a datatable. mod.podcastTableWidget = new AIRTIME.widgets.Table( $('#podcast_table'), //DOM node to create the table inside. @@ -1440,197 +1416,15 @@ var AIRTIME = (function(AIRTIME) { } }); - mod._initPodcastEpisodeDatatable(); - // On double click, open a table showing the selected podcast's episodes - // in the left-hand pane. + // Edit podcast in right-side pane upon double click mod.podcastTableWidget.assignDblClickHandler(function () { - var podcast = mod.podcastDataTable.fnGetData(this); - openPodcastEpisodeTable(podcast); + AIRTIME.podcast.editSelectedPodcasts(); }); mod.podcastDataTable = mod.podcastTableWidget.getDatatable(); $datatables[mod.DataTableTypeEnum.PODCAST] = mod.podcastDataTable; }; - /** - * Initialize the podcast episode view for the left-hand pane - * - * @private - */ - mod._initPodcastEpisodeDatatable = function () { - var buttons = { - backBtn: { - title : $.i18n._('Back to Podcasts'), - iconClass : 'icon-chevron-left', - extraBtnClass : 'btn-small', - elementId : '', - eventHandlers : { - click: function () { - $("#library_filter").text($.i18n._("Podcasts")); - mod.setCurrentTable(mod.DataTableTypeEnum.PODCAST); - } - }, - validateConstraints: function () { return true; } - } - }, - defaults = AIRTIME.widgets.Table.getStandardToolbarButtons(); - - /** - * Check the import statuses of each selected episode to see which - * buttons should be enabled or disabled. - * - * @param shouldBeImported whether or not the selected item(s) - * should be imported to obtain a valid result. - * - * @returns {boolean} true if all selected episodes are valid and - * the button should be enabled, otherwise false. - */ - var checkSelectedEpisodeImportStatus = function (shouldBeImported) { - var selected = this.getSelectedRows(), isValid = true; - if (selected.length == 0) return false; - $.each(selected, function () { - if (this.ingested < 0) isValid = false; - var isImported = !$.isEmptyObject(this.file); - if (shouldBeImported ? !isImported : isImported) { - isValid = false; - } - }); - return isValid; - }; - - // Setup the default buttons (new, edit, delete) - $.extend(true, defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.NEW], - { - title: "Import", - eventHandlers: { - click: function () { - var episodes = mod.podcastEpisodeTableWidget.getSelectedRows(); - AIRTIME.podcast.importSelectedEpisodes(episodes, mod.podcastEpisodeTableWidget); - } - }, - validateConstraints: function () { - return checkSelectedEpisodeImportStatus.call(this, false); - } - }); - $.extend(true, defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], - { - eventHandlers: { - click: function () { - var episodes = mod.podcastEpisodeTableWidget.getSelectedRows(); - AIRTIME.podcast.editSelectedEpisodes(episodes); - } - }, - validateConstraints: function () { - return checkSelectedEpisodeImportStatus.call(this, true); - } - }); - $.extend(true, defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.DELETE], - { - eventHandlers: { - click: function () { - var data = [], episodes = mod.podcastEpisodeTableWidget.getSelectedRows(); - $.each(episodes, function () { - data.push({id: this.file.id, type: this.file.ftype}); - }); - mod.fnDeleteItems(data); - } - }, - validateConstraints: function () { - return checkSelectedEpisodeImportStatus.call(this, true); - } - }); - - // Reassign these because integer keys take precedence in iteration order - we want to order based on insertion - // FIXME: this is a pretty flimsy way to try to set up iteration order (possibly not xbrowser compatible?) - defaults = { - newBtn : defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.NEW], - editBtn: defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], - delBtn : defaults[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.DELETE] - }; - - $.extend(true, buttons, defaults, { - addToScheduleBtn: { - title : $.i18n._('Add to Schedule'), - iconClass : '', - extraBtnClass : 'btn-small', - elementId : '', - eventHandlers : { - click: function () { - var data = [], selected = mod.podcastEpisodeTableWidget.getSelectedRows(); - $.each(selected, function () { data.push(this.file); }); - mod.addToSchedule(data); - } - }, - validateConstraints: function () { - // TODO: change text + behaviour for playlists, smart blocks, etc. - return checkSelectedEpisodeImportStatus.call(this, true); - } - }, - viewDescBtn: { - title : $.i18n._("View"), - iconClass : "icon-globe", - extraBtnClass : "btn-small", - elementId : "", - eventHandlers : { - click: mod.openPodcastEpisodeDialog - }, - validateConstraints: function () { - return this.getSelectedRows().length == 1; - } - } - }); - - mod.podcastEpisodeTableWidget = AIRTIME.podcast.initPodcastEpisodeDatatable( - $("#podcast_episodes_table"), - { - aoColumns : [ - /* GUID */ { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false }, - /* Ingested */ { "sTitle" : $.i18n._("Imported?") , "mDataProp" : "importIcon" , "sClass" : "podcast_episodes_imported" , "sWidth" : "120px" }, - /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" }, - /* Author */ { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" }, - /* Description */ { "sTitle" : $.i18n._("Description") , "mDataProp" : "description" , "sClass" : "podcast_episodes_description" , "sWidth" : "300px" }, - /* Link */ { "sTitle" : $.i18n._("Link") , "mDataProp" : "link" , "sClass" : "podcast_episodes_link" , "sWidth" : "170px" }, - /* Publication Date */ { "sTitle" : $.i18n._("Publication Date") , "mDataProp" : "pub_date" , "sClass" : "podcast_episodes_pub_date" , "sWidth" : "170px" } - ], - bServerSide : false, - sAjaxSource : null, - // Initialize the table with empty data so we can defer loading - // If we load sequentially there's a delay before the table appears - aaData : {}, - oColVis : { - buttonText: $.i18n._("Columns"), - iOverlayFade: 0, - aiExclude: [0, 1, 2] - }, - oColReorder: { - iFixedColumns: 3 // Checkbox + imported - } - }, - buttons, - { - hideIngestCheckboxes: false, - emptyPlaceholder: { - iconClass: "icon-white icon-th-list", - html: $.i18n._("This podcast doesn't have any episodes!") - + "
" + $.i18n._("Make sure the RSS feed contains audio items (with enclosure tags).") - + "
" + $.i18n._("Learn about podcasts") + "" - } - } - ); - - mod.podcastEpisodeDataTable = $datatables[mod.DataTableTypeEnum.PODCAST_EPISODES] = mod.podcastEpisodeTableWidget.getDatatable(); - mod.podcastEpisodeTableWidget.assignDblClickHandler(function () { - var data = mod.podcastEpisodeDataTable.fnGetData(this); - if (!$.isEmptyObject(data.file)) { - mod.dblClickAdd(data.file, data.file.ftype); - } else { - if (data.ingested >= 0) { // Only import if the file isn't pending - AIRTIME.podcast.importSelectedEpisodes([data], mod.podcastEpisodeTableWidget); - } - } - }); - }; - mod.libraryInit = libraryInit; return AIRTIME; diff --git a/airtime_mvc/public/js/airtime/library/podcast.js b/airtime_mvc/public/js/airtime/library/podcast.js index ac90eb588..c7ce2c548 100644 --- a/airtime_mvc/public/js/airtime/library/podcast.js +++ b/airtime_mvc/public/js/airtime/library/podcast.js @@ -6,6 +6,7 @@ var AIRTIME = (function (AIRTIME) { } mod = AIRTIME.podcast; + mod.episodeTables = {}; var endpoint = '/rest/podcast/', PodcastEpisodeTable; @@ -41,6 +42,7 @@ var AIRTIME = (function (AIRTIME) { successMsg.hide("fast"); }, 5000); AIRTIME.library.podcastDataTable.fnDraw(); + self.$scope.tab.setName(self.$scope.podcast.title); }; /** @@ -121,13 +123,14 @@ var AIRTIME = (function (AIRTIME) { self.$scope.tab.setName(self.$scope.podcast.title); // Add an onclose hook to the tab to remove the table object and the // import listener so we don't cause memory leaks. - if (self.episodeTable) { - self.$scope.tab.assignOnCloseHandler(function () { - self.episodeTable.destroy(); - self.episodeTable = null; + var podcastId = self.$scope.podcast.id.toString(); + self.$scope.tab.assignOnCloseHandler(function () { + if ( AIRTIME.podcast.episodeTables.hasOwnProperty(podcastId) ) { + AIRTIME.podcast.episodeTables[podcastId].destroy(); + AIRTIME.podcast.episodeTables[podcastId] = null; self.$scope.$destroy(); - }); - } + } + }); }; /** @@ -145,21 +148,20 @@ var AIRTIME = (function (AIRTIME) { function StationPodcastController($scope, $http, podcast, tab) { // Super call to parent controller PodcastController.call(this, $scope, $http, podcast, tab); - // @frecuencialibre commenting this out since i think it is never called. @todo delete once confirmed - // this.onSaveCallback = function () { - // $http({ - // method: 'POST', - // url: '/preference/station-podcast-settings', - // headers: {'Content-Type': 'application/x-www-form-urlencoded'}, - // data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() } - // }).success(function (data) { - // jQuery.extend($scope.podcast, data); - // $(".success").text($.i18n._("Podcast settings saved")).slideDown("fast"); - // setTimeout(function () { - // $(".success").slideUp("fast"); - // }, 2000); - // }); - // }; + this.onSaveCallback = function () { + $http({ + method: 'POST', + url: '/preference/station-podcast-settings', + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() } + }).success(function (data) { + jQuery.extend($scope.podcast, data); + $(".success").text($.i18n._("Podcast settings saved")).slideDown("fast"); + setTimeout(function () { + $(".success").slideUp("fast"); + }, 2000); + }); + }; return this; } @@ -324,7 +326,7 @@ var AIRTIME = (function (AIRTIME) { uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+podcast.id, tab = AIRTIME.tabs.openTab(data.html, uid, null); _bootstrapAngularApp(podcast, tab); - + $(".album_names.help_icon").qtip({ content: { text: $.i18n._('Overwrite downloaded podcast episodes\' "Album" metadata tag with the Podcast Name specified above. This album name can then be used as a search criteria by a smartblock.') @@ -346,6 +348,13 @@ var AIRTIME = (function (AIRTIME) { } }); + // Add podcast episode table in right-side panel below podcast edit form + var episodeTable = AIRTIME.podcast.initPodcastEpisodeDatatableWithButtonEvents( + $("#podcast_episodes_" + podcast.id), + podcast.id.toString() + ); + episodeTable.reload(podcast.id); + episodeTable.clearSelection() } /** @@ -431,7 +440,7 @@ var AIRTIME = (function (AIRTIME) { var self = this; self.importListener = setInterval(function () { var podcastId = self.config.podcastId, pendingRows = []; - if (!podcastId) return false; + if (!podcastId) return false; var dt = self.getDatatable(), data = dt.fnGetData(); // Iterate over the table data to check for any rows pending import $.each(data, function () { @@ -502,11 +511,14 @@ var AIRTIME = (function (AIRTIME) { */ mod.addPodcast = function () { $.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) { - // Open the episode view for the newly created podcast in the left-hand pane - AIRTIME.library.podcastEpisodeTableWidget.reload(JSON.parse(json.podcast).id); - AIRTIME.library.podcastTableWidget.clearSelection(); - AIRTIME.library.setCurrentTable(AIRTIME.library.DataTableTypeEnum.PODCAST_EPISODES); + // Refresh left-side library pane to show newly created podcast + AIRTIME.library.podcastDataTable.fnDraw(); + + // close modal $("#podcast_url_dialog").dialog("close"); + + // open newly created podcast in right-side edit pane + _initAppFromResponse(json); }).fail(function (e) { var errors = $("#podcast_url_dialog").find(".errors"); errors.show(200).text(e.responseText); @@ -567,12 +579,11 @@ var AIRTIME = (function (AIRTIME) { return false; } if (this.file && Object.keys(this.file).length > 0) return false; - var podcastId = this.podcast_id; - $.post(endpoint + podcastId + '/episodes', JSON.stringify({ + $.post(endpoint + this.podcast_id + '/episodes', JSON.stringify({ csrf_token: $("#csrf").val(), episode: this }), function () { - dt.reload(podcastId); + dt.reload(dt.config.podcastId); }); remainingDiskSpace -= this.enclosure.length; @@ -581,87 +592,241 @@ var AIRTIME = (function (AIRTIME) { dt.clearSelection(); }; + /** + * Delete one or more podcast episodes. + * + * @param {id:string, type:string}[] data Array of data objects to be deleted + * @param podcastId:string + */ + mod.deleteSelectedEpisodes = function (data, podcastId) { + $.each(data, function () { + AIRTIME.library.fnDeleteItems(data, podcastId); + }); + }; + + /** + * Initialize the podcast episode table with working buttons + */ + mod.initPodcastEpisodeDatatableWithButtonEvents = function (domNode, podcastId) { + + /** + * Check the import statuses of each selected episode to see which + * buttons should be enabled or disabled. + * + * @param shouldBeImported whether or not the selected item(s) + * should be imported to obtain a valid result. + * + * @returns {boolean} true if all selected episodes are valid and + * the button should be enabled, otherwise false. + */ + var checkSelectedEpisodeImportStatus = function (shouldBeImported) { + var selected = this.getSelectedRows(), isValid = true; + if (selected.length == 0) return false; + $.each(selected, function () { + if (this.ingested < 0) isValid = false; + var isImported = !$.isEmptyObject(this.file); + if (shouldBeImported ? !isImported : isImported) { + isValid = false; + } + }); + return isValid; + }; + + // Setup the default buttons (new, edit, delete) + podcastEpisodeButtons = AIRTIME.widgets.Table.getStandardToolbarButtons(); + $.extend(true, podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.NEW], + { + title: "Import", + eventHandlers: { + click: function () { + var episodes = mod.episodeTables[podcastId].getSelectedRows(); + AIRTIME.podcast.importSelectedEpisodes(episodes, mod.episodeTables[podcastId]); + } + }, + validateConstraints: function () { + return checkSelectedEpisodeImportStatus.call(this, false); + } + }); + $.extend(true, podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], + { + eventHandlers: { + click: function () { + var episodes = mod.episodeTables[podcastId].getSelectedRows(); + AIRTIME.podcast.editSelectedEpisodes(episodes); + } + }, + validateConstraints: function () { + return checkSelectedEpisodeImportStatus.call(this, true); + } + }); + $.extend(true, podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.DELETE], + { + eventHandlers: { + click: function () { + var data = [], episodes = mod.episodeTables[podcastId].getSelectedRows(); + $.each(episodes, function () { + data.push({id: this.file.id, type: this.file.ftype}); + }); + AIRTIME.podcast.deleteSelectedEpisodes(data, podcastId); + } + }, + validateConstraints: function () { + return checkSelectedEpisodeImportStatus.call(this, true); + } + }); + + // Reassign these because integer keys take precedence in iteration order - we want to order based on insertion + // FIXME: this is a pretty flimsy way to try to set up iteration order (possibly not xbrowser compatible?) + podcastEpisodeButtons = { + newBtn : podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.NEW], + editBtn: podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], + delBtn : podcastEpisodeButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.DELETE] + }; + + $.extend(true, podcastEpisodeButtons, { + addToScheduleBtn: { + title : $.i18n._('Add to Schedule'), + iconClass : 'icon-plus', + extraBtnClass : 'btn-small', + elementId : '', + eventHandlers : { + click: function () { + var data = [], selected = AIRTIME.podcast.episodeTables[podcastId].getSelectedRows(); + $.each(selected, function () { data.push(this.file); }); + AIRTIME.library.addToSchedule(data); + } + }, + validateConstraints: function () { + // TODO: change text + behaviour for playlists, smart blocks, etc. + return checkSelectedEpisodeImportStatus.call(this, true); + } + }, + viewDescBtn: { + title : $.i18n._("View"), + iconClass : "icon-globe", + extraBtnClass : "btn-small", + elementId : "", + eventHandlers : { + click: function () { + AIRTIME.library.openPodcastEpisodeDialog(podcastId); + } + }, + validateConstraints: function () { + return this.getSelectedRows().length == 1; + } + } + }); + + mod.episodeTables[podcastId] = AIRTIME.podcast.initPodcastEpisodeDatatable( + domNode, + podcastEpisodeButtons, + { + hideIngestCheckboxes: false, + emptyPlaceholder: { + iconClass: "icon-white icon-th-list", + html: $.i18n._("This podcast doesn't have any episodes!") + + "
" + $.i18n._("Make sure the RSS feed contains audio items (with enclosure tags).") + + "
" + $.i18n._("Learn about podcasts") + "" + } + } + ); + + mod.podcastEpisodeDataTable = mod.episodeTables[podcastId].getDatatable(); + mod.episodeTables[podcastId].assignDblClickHandler(function () { + var data = mod.podcastEpisodeDataTable.fnGetData(this); + if (!$.isEmptyObject(data.file)) { + mod.dblClickAdd(data.file, data.file.ftype); + } else { + if (data.ingested >= 0) { // Only import if the file isn't pending + AIRTIME.podcast.importSelectedEpisodes([data], mod.episodeTables[podcastId]); + } + } + }); + + return mod.episodeTables[podcastId]; + }; + /** * Initialize the internal datatable for the podcast editor view to hold episode data passed back from the server. * * Selection for the internal table represents episodes marked for ingest and is disabled for ingested episodes. * * @param {jQuery} domNode the jQuery DOM node to create the table inside. - * @param {Object} params JSON object containing datatables parameters to override * @param {Object} buttons JSON object containing datatables button parameters * @param {Object} config JSON object containing internal PodcastEpisodeTable parameters * @param {boolean} config.hideIngestCheckboxes flag denoting whether or not to hide checkboxes for ingested items * * @returns {Table} the created Table object */ - mod.initPodcastEpisodeDatatable = function (domNode, params, buttons, config) { - if ('slideToggle' in buttons) { - buttons = $.extend(true, { - slideToggle: { - title: '', - iconClass: 'spl-no-r-margin icon-chevron-up', - extraBtnClass: 'toggle-editor-form', - elementId: '', - eventHandlers: {}, - validateConstraints: function () { return true; } - } - }, buttons); - } - params = $.extend(true, params, - { - bDeferRender: true, - oColVis: { - buttonText: $.i18n._("Columns"), - iOverlayFade: 0, - aiExclude: [0] - }, - oColReorder: { - iFixedColumns: 1 // Checkbox - }, - fnCreatedRow: function(nRow, aData, iDataIndex) { - var self = this; - if (aData.file && Object.keys(aData.file).length > 0) { - $(nRow).draggable({ - helper: function () { - var $row = $(this), data = self._datatable.fnGetData(nRow); - $row.data("aData", data.file); - self.selectRow(this, data, self.SELECTION_MODE.SINGLE, $row.index()); - var selected = self.getSelectedRows().length, container, - width = self._$wrapperDOMNode.closest(".dataTables_wrapper").outerWidth(), message; + mod.initPodcastEpisodeDatatable = function (domNode, buttons, config) { - message = sprintf($.i18n._(selected > 1 ? "Adding %s Items" : "Adding %s Item"), selected); - container = $('
').attr('id', 'draggingContainer').append('') - .find("tr").append('').find("td") - .attr("colspan", 100).width(width).css("max-width", "none") - .addClass("ui-state-highlight").append(message).end().end(); + params = { + aoColumns : [ + /* GUID */ { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false }, + /* Ingested */ { "sTitle" : $.i18n._("Imported?") , "mDataProp" : "importIcon" , "sClass" : "podcast_episodes_imported" , "sWidth" : "120px" }, + /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" }, + /* Author */ { "sTitle" : $.i18n._("Author") , "mDataProp" : "author" , "sClass" : "podcast_episodes_author" , "sWidth" : "170px" }, + /* Description */ { "sTitle" : $.i18n._("Description") , "mDataProp" : "description" , "sClass" : "podcast_episodes_description" , "sWidth" : "300px" }, + /* Link */ { "sTitle" : $.i18n._("Link") , "mDataProp" : "link" , "sClass" : "podcast_episodes_link" , "sWidth" : "170px" }, + /* Publication Date */ { "sTitle" : $.i18n._("Publication Date") , "mDataProp" : "pub_date" , "sClass" : "podcast_episodes_pub_date" , "sWidth" : "170px" } + ], + bServerSide : false, + sAjaxSource : null, + // Initialize the table with empty data so we can defer loading + // If we load sequentially there's a delay before the table appears + aaData : {}, + oColVis : { + buttonText: $.i18n._("Columns"), + iOverlayFade: 0, + aiExclude: [0, 1, 2] + }, + bDeferRender: true, + oColReorder: { + iFixedColumns: 3 // Checkbox + imported + }, + fnCreatedRow: function(nRow, aData, iDataIndex) { + var self = this; + if (aData.file && Object.keys(aData.file).length > 0) { + $(nRow).draggable({ + helper: function () { + var $row = $(this), data = self._datatable.fnGetData(nRow); + $row.data("aData", data.file); + self.selectRow(this, data, self.SELECTION_MODE.SINGLE, $row.index()); + var selected = self.getSelectedRows().length, container, + width = self._$wrapperDOMNode.closest(".dataTables_wrapper").outerWidth(), message; - return container; - }, - tolerance: 'pointer', - cursor: 'move', - cursorAt: { - top: 20, - left: Math.floor(self._datatable.outerWidth() / 2) - }, - distance: 25, // min-distance for dragging - connectToSortable: $("#show_builder_table, .active-tab .spl_sortable") - }); - } - }, - fnDrawCallback: function () { - AIRTIME.library.drawEmptyPlaceholder(this); - // Hide the processing div - var dt = this.getDatatable(); - !dt || dt.closest(".dataTables_wrapper").find(".dataTables_processing").css("visibility", "hidden"); + message = sprintf($.i18n._(selected > 1 ? "Adding %s Items" : "Adding %s Item"), selected); + container = $('
').attr('id', 'draggingContainer').append('') + .find("tr").append('').find("td") + .attr("colspan", 100).width(width).css("max-width", "none") + .addClass("ui-state-highlight").append(message).end().end(); + + return container; + }, + tolerance: 'pointer', + cursor: 'move', + cursorAt: { + top: 20, + left: Math.floor(self._datatable.outerWidth() / 2) + }, + distance: 25, // min-distance for dragging + connectToSortable: $("#show_builder_table, .active-tab .spl_sortable") + }); } + }, + fnDrawCallback: function () { + AIRTIME.library.drawEmptyPlaceholder(this); + // Hide the processing div + var dt = this.getDatatable(); + !dt || dt.closest(".dataTables_wrapper").find(".dataTables_processing").css("visibility", "hidden"); } - ); + } if (typeof PodcastEpisodeTable === 'undefined') { _initPodcastEpisodeTable(); } - - var podcastEpisodesTableWidget = new PodcastEpisodeTable( + + var podcastEpisodeTableObj = new PodcastEpisodeTable( domNode, // DOM node to create the table inside. true, // Enable item selection buttons, // Toolbar buttons @@ -669,8 +834,8 @@ var AIRTIME = (function (AIRTIME) { config // Internal config ); - podcastEpisodesTableWidget.getDatatable().addTitles("td"); - return podcastEpisodesTableWidget; + podcastEpisodeTableObj.getDatatable().addTitles("td"); + return podcastEpisodeTableObj; }; return AIRTIME;