').data({
'id': app.mainObjectId,
'type': 'layout'
});
app.dropItemAdd($tempLayoutObj, card);
}
} else {
// Select new card
$(card).addClass('card-selected');
$(card).parent('.toolbar-pane-content').addClass('selected');
// Save selected card data
this.selectedCard = card;
// Show designer overlay
$('.custom-overlay').show().unbind().click(() => {
this.deselectCardsAndDropZones();
});
// Set droppable areas as active
if(dropTo === 'all' && subType === 'permissions') {
$('.ui-droppable.permissionsModifiable').addClass('ui-droppable-active');
} else {
$('[data-type="' + dropTo + '"].ui-droppable.editable').addClass('ui-droppable-active');
}
}
}
};
/**
* Select media so it can be used
* @param {object} media - DOM card to select/activate
*/
Toolbar.prototype.selectMedia = function(media, data) {
const alreadySelected = $(media).hasClass('media-selected');
// Deselect previous selections
this.deselectCardsAndDropZones();
if(!alreadySelected) {
// Select row in the table
$(media).addClass('media-selected');
$(media).parent('.toolbar-pane-content').addClass('selected');
// Create temp object to simulate a card and use it as the selected card
this.selectedCard = $('
').data({
type: 'media',
mediaId: data.mediaId,
subType: data.mediaType
});
// Show designer overlay
$('.custom-overlay').show().unbind().click(() => {
this.deselectCardsAndDropZones();
});
// Set droppable regions as active
$('[data-type="region"].ui-droppable.editable').addClass('ui-droppable-active');
}
};
/**
* Deselect all the cards and remove the overlay on the drop zones
*/
Toolbar.prototype.deselectCardsAndDropZones = function() {
// Deselect other cards
this.DOMObject.find('.toolbar-card.card-selected').removeClass('card-selected');
// Deselect other media
this.DOMObject.find('.media-table tr.media-selected').removeClass('media-selected');
// Remove content selected class
this.DOMObject.find('.toolbar-pane-content.selected').removeClass('selected');
// Remove drop class from droppable elements
$('.ui-droppable').removeClass('ui-droppable-active');
// Disable multi-select mode
if(this.parent.editorContainer.hasClass('multi-select')) {
this.toggleMultiselectMode(false);
}
// Hide designer overlay
$('.custom-overlay').hide().unbind();
// Deselect card
this.selectedCard = {};
};
/**
* Create new tab
*/
Toolbar.prototype.createNewTab = function(menu) {
let moduleListFiltered = [];
let usersListFiltered = [];
const self = this;
// Filter module list to create the types for the filter
modulesList.forEach(element => {
if(element.assignable == 1 && element.regionSpecific == 0) {
moduleListFiltered.push({
type: element.type,
name: element.name
});
}
});
usersList.forEach(element => {
usersListFiltered.push({
userId: element.userId.toString(),
name: element.userName
});
});
this.menuItems[menu].content.push({
name: toolbarTrans.tabName.replace('%tagId%', self.menuItems[menu].content.length),
filters: {
name: {
name: toolbarTrans.searchFilters.name,
value: ''
},
tag: {
name: toolbarTrans.searchFilters.tag,
value: ''
},
type: {
name: toolbarTrans.searchFilters.type,
values: moduleListFiltered
},
owner: {
name: toolbarTrans.searchFilters.owner,
values: usersListFiltered
},
}
});
this.menuItems[menu].selectedTab = this.menuItems[menu].content.length - 1;
self.savePrefs();
};
/**
* Delete tab
* @param {number} menu
*/
Toolbar.prototype.deleteTab = function(menu) {
// Remove menu option from the array
this.menuItems.splice(menu, 1);
if(this.openedMenu == menu) {
// Deselect menu if we're closing the selected one
this.openedMenu = -1;
} else if(this.openedMenu < menu) {
// If the deleted menu is lower than the selected, update the selected index
this.openedMenu -= 1;
}
// Deselect previous selections
this.deselectCardsAndDropZones();
// Save user preferences
this.savePrefs();
this.render();
};
/**
* Delete all tabs
*/
Toolbar.prototype.deleteAllTabs = function() {
for(let index = this.menuItems.length - 1;index >= this.fixedTabs;index--) {
this.menuItems.splice(index, 1);
}
if(this.openedMenu >= this.fixedTabs) {
this.openedMenu = -1;
}
// Deselect previous selections
this.deselectCardsAndDropZones();
// Save user preferences
this.savePrefs();
this.render();
};
/**
* Opens a new tab and search for the given media type
* @param {string} type - Type of media
*/
Toolbar.prototype.openNewTabAndSearch = function(type) {
// Open library library window
this.openMenu(this.libraryMenuIndex);
// Create a new tab
this.createNewTab(this.libraryMenuIndex);
// Switch the selected tab's Type select box to the type we want
this.menuItems[this.libraryMenuIndex].content[this.menuItems[this.libraryMenuIndex].selectedTab].filters.type.value = type;
//this.DOMObject.find('#media-search-form-' + this.openedMenu + ' #input-type-' + this.openedMenu).val(type);
// Search/Load Content
this.loadContent(this.openedMenu);
};
/**
* Media form callback
*/
Toolbar.prototype.mediaContentCreateWindow = function(menu) {
const self = this;
const app = this.parent;
// Deselect previous selections
self.deselectCardsAndDropZones();
// Get search window Jquery object
const $libraryWindowContent = self.DOMObject.find('#content-' + menu + '.library-content');
if(this.menuItems[menu].content.length === 0) {
this.createNewTab(menu);
}
// Render template
const html = ToolbarMediaSearchTemplate({
menuIndex: menu,
menuObj: this.menuItems[menu],
trans: toolbarTrans,
closeTabs: this.menuItems[menu].content.length > 1
});
// Append template to the search main div
self.DOMObject.find('#media-search-container-' + menu).html(html);
// Set paging max to 5
$.fn.DataTable.ext.pager.numbers_length = 5;
// Make search window to be draggable and resizable
$libraryWindowContent
.appendTo('.editor-bottom-bar > nav')
.draggable({
containment: 'window',
scroll: false,
handle: '.drag-handle'
})
.resizable({
minWidth: 640
}).off('dragstart dragstart resizestart resizestop dragstop').on('dragstart',
function() {
// Remove right sticky css
$(this).css('right', 'auto');
}).on('resizestart',
function() {
self.tablePositionUpdate($libraryWindowContent);
}
).on('resizestop dragstop',
function(event, ui) {
// Save only if we're not in hide mode
if(!$(this).hasClass('hide-mode')) {
// Save window positioning
self.menuItems[menu].searchPosition = {
width: $(this).width(),
height: $(this).height(),
top: $(this).position().top,
left: $(this).position().left
};
self.savePrefs();
self.tablePositionUpdate($libraryWindowContent);
}
}
);
// If we have set positions, set them on load
if(self.menuItems[menu].searchPosition != undefined) {
const position = self.menuItems[menu].searchPosition;
if(position.left + position.width > $(window).width()){
position.left = $(window).width() - position.width;
}
if(position.top + position.height > $(window).height()) {
position.top = $(window).height() - position.height;
}
if(position.left < 0) {
position.left = 0;
}
if(position.top < 0) {
position.top = 0;
}
$libraryWindowContent.width(position.width);
$libraryWindowContent.height(position.height);
$libraryWindowContent.css({top: position.top});
$libraryWindowContent.css({left: position.left});
}
// Search content window buttons handling
$libraryWindowContent.find('.btn-window-close').off().click(function() {
self.openMenu($(this).data('menu'));
});
$libraryWindowContent.find('.btn-window-new-tab').off().click(function() {
// Get menu index
const menu = $(this).data('menu');
// Create new tab
self.createNewTab(menu);
// Populate selected tab
self.mediaContentCreateWindow(menu);
});
$libraryWindowContent.find('.media-search-tab:not(.active):not(.media-tab-close)').off().click(function(ev) {
ev.stopPropagation();
// Get tab index
const tab = $(this).data('tab');
// Change selected tav
self.menuItems[menu].selectedTab = tab;
// Populate selected tab
self.mediaContentCreateWindow(menu);
});
$libraryWindowContent.find('.media-tab-close').off().click(function(ev) {
ev.stopPropagation();
// Get tab index
const tabToDelete = $(this).parent().data('tab');
let selectedTab = self.menuItems[menu].selectedTab;
// Select another tab
if(selectedTab >= tabToDelete && selectedTab > 0) {
selectedTab--;
}
// Delete tab and content
self.menuItems[menu].content.splice(tabToDelete, 1);
// Select new tab
self.menuItems[menu].selectedTab = selectedTab;
// Update tab names
self.updateTabNames(menu);
// Populate selected tab
self.mediaContentCreateWindow(menu);
});
// Populate selected tab
self.mediaContentPopulateTable(menu);
// Create media queue if in backup
if(!$.isEmptyObject(self.selectedQueue)){
self.createQueue(menu);
}
};
/**
* Media content populate table
*/
Toolbar.prototype.mediaContentPopulateTable = function(menu) {
const self = this;
const tabIndex = self.menuItems[0].selectedTab;
const tabObj = self.menuItems[menu].content[self.menuItems[0].selectedTab];
// Destroy previous table
self.DOMObject.find('#media-table-' + menu).DataTable().destroy();
self.DOMObject.find('#media-table-' + menu).empty();
var mediaTable = self.DOMObject.find('#media-table-' + menu).DataTable({
"language": dataTablesLanguage,
"lengthMenu": [5, 10],
"pageLength": 5,
"autoWidth": false,
serverSide: true, stateSave: true,
searchDelay: 3000,
"order": [[1, "asc"]],
"filter": false,
ajax: {
url: librarySearchUrl + '?assignable=1&retired=0',
"data": function(d) {
$.extend(d, self.DOMObject.find('#media-search-container-' + menu + ' #media-search-form-' + tabIndex).serializeObject());
}
},
"columns": [
{
"sortable": false,
"data": function(data, type, row, meta) {
if(type !== "display")
return "";
// Create a click-able span
return "
";
}
},
{"data": "mediaId"},
{"data": "name"},
{"data": "mediaType"},
{
"sortable": false,
"data": dataTableCreateTags
},
{
"name": "mediaId",
"data": null,
"render": function(data, type, row, meta) {
if(type === "display") {
// Return only the image part of the data
if(data.thumbnailUrl === '')
return '';
else
return '
';
return data;
} else {
return row.mediaId;
}
}
}
]
});
mediaTable.on('draw', function(e, settings) {
dataTableDraw(e, settings);
// Clicky on the +spans
self.DOMObject.find(".assignItem").click(function() {
// Get the row that this is in.
var data = mediaTable.row($(this).closest("tr")).data();
if(self.useQueue) {
self.addToQueue(menu, data);
} else {
self.selectMedia($(this).closest('tr'), data);
}
});
self.updateTabNames(menu);
self.tablePositionUpdate(self.DOMObject.find('#content-' + menu + '.library-content'));
});
mediaTable.on('processing.dt', dataTableProcessing);
// Refresh the table results
var filterRefresh = function(mediaTable, tabObj) {
// Save filter options
tabObj.filters.name.value = self.DOMObject.find('#media-search-form-' + tabIndex + ' #input-name-' + tabIndex).val();
tabObj.filters.tag.value = self.DOMObject.find('#media-search-form-' + tabIndex + ' #input-tag-' + tabIndex).val();
tabObj.filters.type.value = self.DOMObject.find('#media-search-form-' + tabIndex + ' #input-type-' + tabIndex).val();
tabObj.filters.owner.value = self.DOMObject.find('#media-search-form-' + tabIndex + ' #input-owner-' + tabIndex).val();
self.savePrefs();
self.updateTabNames(menu);
// Reload table
mediaTable.ajax.reload();
};
// Prevent filter form submit and bind the change event to reload the table
self.DOMObject.find('#media-search-form-' + tabIndex).on('submit', function(e) {
e.preventDefault();
return false;
});
// Bind seach action to refresh the results
self.DOMObject.find('#media-search-form-' + tabIndex + ' select, input[type="text"]').change(_.debounce(function() {
filterRefresh(mediaTable, tabObj);
}, 500));
self.DOMObject.find('#media-search-form-' + tabIndex + ' input[type="text"]').on('input', _.debounce(function() {
filterRefresh(mediaTable, tabObj);
}, 500));
// Initialize tagsinput
self.DOMObject.find('#media-search-form-' + tabIndex + ' input[data-role="tagsinput"]').tagsinput();
self.DOMObject.find('#media-table-' + menu).off('click').on('click', '#tagDiv .btn-tag', function() {
// See if its the first element, if not add comma
var tagText = $(this).text();
// Add text to form
self.DOMObject.find('#media-search-form-' + tabIndex + ' input[data-role="tagsinput"]').tagsinput('add', tagText, {allowDuplicates: false});
});
};
/**
* Update tab height
*/
Toolbar.prototype.tablePositionUpdate = function(container) {
// Calculate table container height
const tableContainerHeight = container.find('.media-search-controls').height() + container.find('.media-search-form:not(.hidden)').height() + container.find('.dataTables_wrapper').height();
// Set resizable min height
if(container.resizable('instance') != undefined) {
container.resizable('option', 'minHeight', tableContainerHeight);
}
// Fix height if bigger than the min
if(container.height() < tableContainerHeight) {
container.height(tableContainerHeight);
}
};
/**
* Update tab name
*/
Toolbar.prototype.updateTabNames = function(menu) {
for(let tab = 0;tab < this.menuItems[menu].content.length;tab++) {
const tabContent = this.menuItems[menu].content[tab];
const customFilter = tabContent.filters;
// Change tab name to reflect the search query
if(customFilter.name.value != '' && customFilter.name.value != undefined) {
tabContent.name = '"' + customFilter.name.value + '"';
} else {
tabContent.name = toolbarTrans.tabName.replace('%tagId%', tab);
}
if(customFilter.tag.value != '' && customFilter.tag.value != undefined) {
tabContent.name += ' {' + customFilter.tag.value + '} ';
}
if(customFilter.type.value != '' && customFilter.type.value != undefined) {
tabContent.name += ' [' + customFilter.type.value + '] ';
}
// Change
this.DOMObject.find('#content-' + menu + ' #tab-name-' + tab).html(tabContent.name);
}
};
/**
* Mark/Unmark as favourite
*/
Toolbar.prototype.toggleFavourite = function(target) {
let favouriteModulesArray = this.menuItems[this.widgetMenuIndex].favouriteModules;
let markAsFav = false;
const $card = $(target).parent('.toolbar-card[data-type="module"]');
const cardType = $card.data().subType;
const positionInArray = $.inArray(cardType, favouriteModulesArray);
// Add/remove from the fav array
if(positionInArray > -1) {
// Remove from favourites
favouriteModulesArray.splice(positionInArray, 1);
} else {
// Add to favourites
markAsFav = true;
favouriteModulesArray.push(cardType);
}
// Show notification
toastr.success((markAsFav) ? toolbarTrans.addedToFavourites : toolbarTrans.removedFromFavourites, '', { positionClass: 'toast-bottom-right' });
// Save user preferences
this.savePrefs();
// Reload toolbar widget content
this.loadContent(2);
};
/**
* Queue
*/
Toolbar.prototype.createQueue = function(menu, target = null) {
const self = this;
let html = '';
if(this.selectedQueue != undefined && !$.isEmptyObject(this.selectedQueue)) {
// Get html from backup
html = $(this.selectedQueue)[0].outerHTML;
// Remove previous queue
this.destroyQueue(menu);
} else {
html = ToolbarMediaQueueTemplate({
trans: toolbarTrans
});
}
// Append the queue to the library search window
this.DOMObject.find('#content-' + menu).append(html);
// Handle destroy queue button
this.DOMObject.find('#content-' + menu + ' .btn-queue-close').click(function() {
self.destroyQueue(menu);
});
// Update queue position
this.updateQueue(menu);
// Add element to queue
if(target){
this.addToQueue(menu, target);
}
// Make queue sortable
this.DOMObject.find('#content-' + menu + ' .media-add-queue-list').sortable();
// Handle buttons
const $mediaQueue = this.DOMObject.find('#content-' + menu + ' .media-add-queue');
$mediaQueue.find('.media-add-queue-buttons').on('click', '.btn.active', function() {
const buttonType = $(this).data('type');
if(buttonType == 'toRegion' || buttonType == 'toPlaylist') {
self.queueAddToRegionPlaylist(menu);
} else if(buttonType == 'selectRegion') {
self.queueToggleToAddMode(menu);
} else if(buttonType == 'cancel') {
self.queueToggleToAddMode(menu, false);
}
});
// Handle remove queue button
$mediaQueue.on('click', '.queue-element-remove', function() {
self.removeFromQueue(menu, $(this));
});
};
Toolbar.prototype.updateQueue = function(menu) {
const $mediaQueue = this.DOMObject.find('#content-' + menu + ' .media-add-queue');
const app = this.parent;
// Position queue
$mediaQueue.css('left', - $mediaQueue.outerWidth()).show();
// Update queue button status
$mediaQueue.find('.media-add-queue-buttons .btn').removeClass('active'); // Remove active from all buttons
if($mediaQueue.parent().hasClass('hide-mode')) {
$mediaQueue.find('.btn-queue-close').hide();
$mediaQueue.find('.media-add-queue-buttons button[data-type="cancel"]').addClass('active');
} else {
$mediaQueue.find('.btn-queue-close').show();
if(app.mainObjectType == 'playlist') {
$mediaQueue.find('.media-add-queue-buttons button[data-type="toPlaylist"]').addClass('active');
} else if(app.selectedObject.type === 'region') {
$mediaQueue.find('.media-add-queue-buttons button[data-type="toRegion"]').addClass('active');
} else {
$mediaQueue.find('.media-add-queue-buttons button[data-type="selectRegion"]').addClass('active');
}
}
// Show drop overlay if queue has elements
if($mediaQueue.find('.queue-element').length > 0) {
this.queueToggleOverlays(menu);
} else {
this.queueToggleOverlays(menu, false);
}
// Save backup
this.selectedQueue = $mediaQueue;
};
Toolbar.prototype.destroyQueue = function(menu) {
// Destroy queue element
$(this.DOMObject.find('.media-add-queue')).remove();
// Hide drop overlay
this.queueToggleOverlays(menu, false);
// Clear media backup
this.selectedQueue = {};
};
Toolbar.prototype.addToQueue = function(menu, target) {
const self = this;
if(this.DOMObject.find('.media-add-queue').length == 0) {
this.createQueue(menu, target);
} else {
// Create a new element with a template
const newElementHTML = ToolbarMediaQueueElementTemplate({
target: target,
trans: toolbarTrans
});
// Add data to the new element and create a jquery object
const $newElement = $(newElementHTML).data(target);
// Add new element to the list
this.DOMObject.find('#content-' + menu + ' .media-add-queue-list').append(
$newElement
);
// Update queue position
this.updateQueue(menu);
}
};
Toolbar.prototype.removeFromQueue = function(menu, target) {
const $mediaList = $(target).parents('.media-add-queue-list');
// Remove element
$(target).parent().remove();
// If the list is empty, remove it
if($mediaList.find('div').length == 0) {
this.destroyQueue(menu);
} else {
// Update queue position
this.updateQueue(menu);
}
};
Toolbar.prototype.queueToggleOverlays = function(menu, enable = true) {
const $mediaQueue = this.DOMObject.find('#content-' + menu + ' .media-add-queue');
// Mark queue as add enabled/disabled
$mediaQueue.data('toAdd', enable);
if(enable) {
// Show designer overlay
$('.custom-overlay').show();
// Set droppable areas as active
$('[data-type="region"].ui-droppable.editable').addClass('ui-droppable-active');
} else {
this.deselectCardsAndDropZones();
}
};
Toolbar.prototype.queueToggleToAddMode = function(menu, enable = true) {
const $mediaQueue = this.DOMObject.find('#content-' + menu + ' .media-add-queue');
const self = this;
// Show/hide table container
$mediaQueue.parent().toggleClass('hide-mode', enable);
// Enable/disable drag
$mediaQueue.parent().resizable(enable ? 'disable' : 'enable');
if(enable) {
// Click on overlay do toggle add mode
$('.custom-overlay').unbind().click(() => {
self.queueToggleToAddMode(menu, false);
});
}
// Update queue position
this.updateQueue(menu);
};
Toolbar.prototype.queueAddToRegionPlaylist = function(menu) {
const app = this.parent;
let mediaQueueArray = [];
this.selectedQueue.find('.queue-element').each(function() {
mediaQueueArray.push($(this).attr('id'));
});
let playlistId = null;
// Get playlist id
if(app.selectedObject.type == 'region') {
playlistId = app.getElementByTypeAndId('region', app.selectedObject.id).playlists.playlistId;
// Add media queue to playlist
app.addMediaToPlaylist(playlistId, mediaQueueArray);
} else if(app.mainObjectType == 'playlist' && app.playlist != undefined) {
app.playlist.addMedia(mediaQueueArray);
}
// Destroy queue
this.destroyQueue(menu);
};
/**
* Revert last action
*/
Toolbar.prototype.toggleMultiselectMode = function(forceSelect = null) {
const self = this;
const app = this.parent;
const timeline = app.timeline;
const editorContainer = app.editorContainer;
const updateTrashContainer = function() {
// Upate trash container status
self.DOMObject.find('#trashContainer').toggleClass('active', (timeline.DOMObject.find('.playlist-widget.multi-selected').length > 0));
};
// Check if needs to be selected or unselected
let multiSelectFlag = (forceSelect != null) ? forceSelect : !editorContainer.hasClass('multi-select');
// Toggle multi select class on container
editorContainer.toggleClass('multi-select', multiSelectFlag);
// Toggle class on button
this.DOMObject.find('#multiSelectContainer').toggleClass('multiselect-active', multiSelectFlag);
if(multiSelectFlag) {
// Show overlay
$('.custom-overlay').show().unbind().click(() => {
self.deselectCardsAndDropZones();
});
// Disable timeline sort
timeline.DOMObject.find('#timeline-container').sortable('disable');
// Enable select for each widget
timeline.DOMObject.find('.playlist-widget.deletable').removeClass('selected').unbind().click(function(e) {
e.stopPropagation();
$(this).toggleClass('multi-selected');
updateTrashContainer();
});
updateTrashContainer();
} else {
// Hide designer overlay
$('.custom-overlay').hide().unbind();
// Re-render timeline
app.renderContainer(timeline);
// Re-render toolbar
app.renderContainer(this);
}
};
module.exports = Toolbar;