';
$('#' + name).append(tag);
break;
case "typeahead":
$('#' + name).closest('.control-group').addClass('success');
var newOption = new Option(result['value'], result['lastID'], true, true);
$('#' + name).empty().append(newOption).trigger('change');
$('#' + name).trigger({
type: 'select2:select',
params: {
data: {id: result['lastID'], text: result['value'], name: result['value']}
}
});
$('#' + name).trigger('changeSelection');
break;
case "multiselectajax":
window[name].addRow(result['lastID'], result['value']);
break;
case "callback":
window[name](result);
break;
case "classCallback":
eval(name)(result);
break;
default:
$('#' + name).closest('.control-group').addClass('success');
$('#' + name).append($("").attr("value", result["lastID"]).text(result["value"]));
$('#' + name).val(result["lastID"]);
$('#select2-' + name + '-container').html(result["value"]);
}
}
} else {
// Add extra data to extras so it's passed to quick_form file
if (typeof result['extraData'] !== 'undefined') {
// Parse extras since it's JSON string
extras = JSON.parse(extras);
// Assign extraData to extras object
extras = Object.assign(extras, result['extraData']);
// Stringify extras object
extras = JSON.stringify(extras);
}
loadQuickModal(model, appID, result['data'], result['fields'], result['alerts'], existingIdValue, extras);
}
}
});
}
/**
* Catch the cancel event
*
* @param name
* @param inputType
*/
function quickCancel(name, inputType) {
if (typeof name !== 'undefined') {
switch (inputType) {
case "callback":
window[name](null);
break;
}
}
}
/**
* Hide a quick modal.
* Note: quickCancel will be called via on("hidden") trigger on the modal.
*
* @param modalId
*/
function quickModalHide(modalId) {
if (modalId) {
$('#' + modalId).modal('hide');
}
}
/**
* This function will init the multi select for users and fixes the empty multiselect problem
*
* @param name
*/
function initMultiSelectUsers(name) {
fillEmptyMultiSelect($('#' + name + 'Not'));
fillEmptyMultiSelect($('#' + name));
$('#add-' + name).click(function () {
$('#' + name + 'Not option:selected').remove().appendTo('#' + name).prop("selected", false);
fillEmptyMultiSelect($('#' + name + 'Not'));
$('#' + name).find("option[value='']").remove();
});
$('#remove-' + name).click(function () {
$('#' + name + ' option:selected').remove().appendTo('#' + name + 'Not').prop("selected", false);
fillEmptyMultiSelect($('#' + name));
$('#' + name + 'Not').find("option[value='']").remove();
});
}
/**
* Fix for empty multiselect
*
* @param element
*/
function fillEmptyMultiSelect(element) {
if (element.has('option').length == 0) {
element.append("");
}
}
function confirmBoxRedirect(text, url) {
bootbox.confirm(text, function (result) {
if (result) location.href = url;
});
}
function initMultiSelectCustomers(name) {
$('#add-' + name).click(function () {
return !$('#' + name + 'Not option:selected').remove().appendTo('#' + name);
});
$('#remove-' + name).click(function () {
return !$('#' + name + ' option:selected').remove().appendTo('#' + name + 'Not');
});
}
/**
* This function will init the multi select for users and fixes the empty multiselect problem
*
* @param name
*/
function initMultiSelectUsers(name) {
fillEmptyMultiSelect($('#' + name + 'Not'));
fillEmptyMultiSelect($('#' + name));
$('#add-' + name).click(function () {
$('#' + name + 'Not option:selected').remove().appendTo('#' + name).prop("selected", false);
fillEmptyMultiSelect($('#' + name + 'Not'));
$('#' + name).find("option[value='']").remove();
});
$('#remove-' + name).click(function () {
$('#' + name + ' option:selected').remove().appendTo('#' + name + 'Not').prop("selected", false);
fillEmptyMultiSelect($('#' + name));
$('#' + name + 'Not').find("option[value='']").remove();
});
}
/**
* Fix for empty multiselect
*
* @param element
*/
function fillEmptyMultiSelect(element) {
if (element.has('option').length == 0) {
element.append("");
}
}
function submitMultiSelectCustomers(name) {
$('#' + name + ' option').prop('selected', true);
$('#' + name + 'Not option:first-child').prop('selected', true);
}
function getMultiSelectCustomers(name, selected) {
var customerList = Array();
var parsed = JSON.parse(selected);
for (var x in parsed) {
customerList[parsed[x]] = parsed[x];
}
$.ajax({
type: 'POST',
url: dataApps[1] + 'index.php?page=users&ajax=klanten&type=list',
dataType: 'json',
success: function (data) {
if (data != "") {
var options = "";
var notOptions = "";
$("#" + name + " option").remove();
$("#" + name + "Not option").remove();
for (var key in data) {
if (customerList.indexOf(data[key].id) > 0) {
options += "";
//$("#"+name).append($("").attr("value",data[key].id).text(data[key].name));
} else {
notOptions += "";
//$("#"+name+"Not").append($("").attr("value",data[key].id).text(data[key].name));
}
}
$("#" + name).append(options);
$("#" + name + "Not").append(notOptions);
//if (customerList.length == 0) $("#"+name).append($("").attr("value",""));
} else {
$("#" + name + " option").remove();
$("#" + name + "Not option").remove();
}
$(document).ready(function () {
$('.hidden-actions').show();
});
}
});
}
function showSuccess(text, delay, fadeOutCallback) {
if (typeof delay === 'undefined') {
delay = 10000;
}
var rand = new Date().getTime();
var delayScript = "";
if (delay > 0) {
var fade = '.fadeOut()';
if (typeof fadeOutCallback !== 'undefined' && fadeOutCallback !== null) {
fade = '.fadeOut(' + fadeOutCallback + ')';
}
delayScript = "";
}
return "
" + text + "
" + delayScript;
}
function showSucces(text, delay, fadeOutCallback) {
return showSuccess(text, delay, fadeOutCallback);
}
/**
* Show an error message
*
* @param {string} text
* @param {number} delay
* @param {Function} fadeOutCallback
*
* @return {string}
*/
function showError(text, delay, fadeOutCallback) {
if (typeof delay === 'undefined') {
delay = 10000;
}
var delayScript = "";
var rand = new Date().getTime();
if (delay > 0) {
var fade = '.fadeOut()';
if (typeof fadeOutCallback !== 'undefined' && fadeOutCallback !== null) {
fade = '.fadeOut(' + fadeOutCallback + ')';
}
delayScript = "";
}
return "
" + text + "
" + delayScript;
}
function showWarning(text, delay, fadeOutCallback) {
if (typeof delay === 'undefined') {
delay = 10000;
}
var delayScript = "";
var rand = new Date().getTime();
if (delay > 0) {
var fade = '.fadeOut()';
if (typeof fadeOutCallback !== 'undefined' && fadeOutCallback !== null) {
fade = '.fadeOut(' + fadeOutCallback + ')';
}
delayScript = "";
}
return "
" + text + "
" + delayScript;
}
function showInfo(text, delay, fadeOutCallback) {
if (typeof delay === 'undefined') {
delay = 10000;
}
var rand = new Date().getTime();
var delayScript = "";
if (delay > 0) {
var fade = '.fadeOut()';
if (typeof fadeOutCallback !== 'undefined' && fadeOutCallback !== null) {
fade = '.fadeOut(' + fadeOutCallback + ')';
}
delayScript = "";
}
return "
" + text + "
" + delayScript;
}
/**
* Tag Numbers Type
* @type {{minMultiNumber: jData.tagNumbersType.minMultiNumber, plusMultiNumber: jData.tagNumbersType.plusMultiNumber, delMultiNumber: jData.tagNumbersType.delMultiNumber, addMultiNumber: jData.tagNumbersType.addMultiNumber}}
*/
jData.tagNumbersType = {
minMultiNumber: function (id, name) {
var count = $('#' + name + '_' + id + '_count').val();
count--;
if (count < 1) {
count = 1;
}
$('#' + name + '_' + id + '_count').val(count);
$('#' + name + '_' + id + '_label').html(count);
},
plusMultiNumber: function (id, name) {
var count = $('#' + name + '_' + id + '_count').val();
count++;
$('#' + name + '_' + id + '_count').val(count);
$('#' + name + '_' + id + '_label').html(count);
},
delMultiNumber: function (id, name) {
$('#' + name + '_' + id + '_label').closest('li').remove();
},
addMultiNumber: function (name) {
var cname = name.substr(0, 1).toUpperCase() + name.substr(1);
var id = $('#' + name + '_add').val();
var text = $('#select2-' + name + '_add-container').html();
var tArr = text.split('');
text = tArr[1];
if ($("#" + name + '_' + id).length == 0) {
//it doesn't exist
html = '
';
html += '×' + text;
html += '1';
html += '';
html += '';
html += '
',
filterClearBtn: '',
},
});
$( ".main-content" ).on( "keypress", "#multiselect-search-"+this.id, $.proxy(function(e) {
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
if (key == 32) {
this.ajax($("#multiselect-search-" + this.id).val());
}
}, this));
this.ajax();
}
this.ajax = function (query) {
$.ajax({
type: 'post',
url: this.source,
context: this,
dataType: 'json',
data: {query: query},
success: function(data) {
var dataSel = [];
if (data != "") {
for (var key in data) {
dataSel.push({label: data[key]["name"], value: data[key]["id"]});
}
}else{
dataSel.push({label: "", value: 0});
}
$("#" + this.id).multiselect('dataprovider', dataSel);
},
error: function(error) {
console.log("Error:");
console.log(error);
}
});
}
}*/
/**
* @deprecated Use $jData.cfunc.preciseRound
* @param num
* @param dec
* @returns {*}
*/
function precise_round(num, dec) {
if ((typeof num !== 'number') || (typeof dec !== 'number'))
return false;
var num_sign = num >= 0 ? 1 : -1;
return (Math.round((num * Math.pow(10, dec)) + (num_sign * 0.0001)) / Math.pow(10, dec)).toFixed(dec);
}
//z me up scotty
jVars.prevzmpopover = {
id: null,
zindex: 0,
};
$(document).on("click", ".z-me-popover", function () {
var tableActionCol = $(this).parents('td[class^="table-action-col"]');
//$('.popover').not(tableActionCol.find(".popover")).remove();
$('.z-me-popover').not(this).popover('hide');
if (jVars.prevzmpopover.id != null) {
var prevTableActionCol = $(jVars.prevzmpopover.id).parents('td[class^="table-action-col"]');
$(prevTableActionCol).zIndex(jVars.prevzmpopover.zindex);
console.log("deleted prev");
}
jVars.prevzmpopover.id = this;
console.log(tableActionCol);
jVars.prevzmpopover.zindex = $(tableActionCol).zIndex();
$(tableActionCol).zIndex(100000);
console.log("z-index done");
});
$(function () {
$(document).find('.fav-links-items').sortable({
placeholder: 'ui-state-highlight',
activate: function (event, ui) {
var widthItems = ui.helper.width();
$('.ui-state-highlight').css('min-width', widthItems);
},
stop: function () {
var links = [];
$('.ui-state-highlight').css('min-width', '');
$('.fav-links-items').find('.fav-link-item').each(function () {
var linkId = $(this).data('linkid');
links.push(linkId);
});
$.ajax({
type: 'POST',
url: jData.urlB.index("links/ajax/save_sort", 9),
dataType: 'json',
data: {links: links}
});
}
});
});
$(document).ready(function () {
// === start FAV. LINK ===
$(document).on('click', '.add-fav-link-btn, .edit-fav-link', function (e) {
e.preventDefault();
// Get page data
let action = $(this).data('action');
let modalObj = $('#addFavLinkModal');
let currentLinkTitle = '';
let modalTitle = '';
let currentLinkHref = '';
let linkId = 0;
let currentElement = $(this);
if (action === 'edit') {
modalTitle = jData.lng.show('links_edit_link');
linkId = currentElement.closest('.fav-link-item').data('linkid');
currentLinkHref = currentElement.closest('a').attr('href');
currentLinkTitle = currentElement.closest('a').attr('title');
} else {
modalTitle = jData.lng.show('links_add_link');
currentLinkHref = location.href;
let currentDocumentTitle = document.title;
let currentPageTitle = $('.page-header h1').text();
if (currentPageTitle !== '') {
currentLinkTitle = currentPageTitle;
} else {
currentLinkTitle = currentDocumentTitle;
}
}
// Set modal title
modalObj.find('#addFavLinkModalTitle').text(modalTitle)
// hide some items
$('.fav-link-icon').removeClass('open'); // close the fav. link menu
$('.modal[aria-hidden="false"]').modal('hide'); // so we don't have an overlap
$('#fav-link-msg').empty();
// add data and show modal
modalObj.find('#fav-link-name').val(currentLinkTitle);
modalObj.find('#fav-link-href').val(currentLinkHref);
modalObj.find('#fav-exist-link').val(linkId);
modalObj.modal('show'); // show the modal to add a link
});
$(document).on('click', '#save-fav-link-btn', function (e) {
e.preventDefault();
var modalObj = $('#addFavLinkModal');
var linkAlertMessages = $('#fav-link-msg');
var linkName = modalObj.find('#fav-link-name').val();
var linkHref = modalObj.find('#fav-link-href').val();
var linkId = modalObj.find('#fav-exist-link').val();
if ($.trim(linkName) === '' || $.trim(linkHref) === '') {
// show message that there is a problem with the fields
message = showError(jData.clng.show("fill_required_fields"));
linkAlertMessages.empty();
linkAlertMessages.append(message);
} else {
linkAlertMessages.empty();
// Save the data of the links
$.ajax({
type: 'POST',
url: jData.urlB.index("links/ajax/save_link", 1),
dataType: 'json',
data: {
linkName: linkName,
linkHref: linkHref,
linkId: linkId
},
success: function (data) {
// Hide modal
modalObj.modal('hide');
// Fill in links html
$('.fav-link-icon .fav-links-items').empty().html(data.extras.html);
// Open links menu
$('.fav-link-icon').addClass('open');
}
});
}
});
$(document).on('click', '.remove-fav-link', function (e) {
e.preventDefault();
// hide some items
$('.fav-link-icon').removeClass('open'); // close the fav. link menu
$('.modal').modal('hide'); // so we don't have an overlap
$('#fav-link-msg').empty();
bootbox.confirm(jData.clng.show('areyousure'), function (result) {
if (result) {
thisObject = e.target;
var linkItem = thisObject.closest('.fav-link-item');
var linkId = $(linkItem).data('linkid');
// Save the data of the links
$.ajax({
type: 'POST',
url: jData.urlB.index("links/ajax/del_link", 1),
dataType: 'json',
data: {linkId: linkId},
success: function (data) {
// open the link tab
if (data.status === 'success') {
$(linkItem).remove();
$('.fav-link-icon').addClass('open');
}
}
});
} else {
$('.fav-link-icon').addClass('open');
}
});
});
// === end FAV. LINK ===
$(document).on('click', '.dropdown-menu', function (e) {
$(this).hasClass('keepOpen') && e.stopPropagation(); // This replace if conditional.
});
$(document).on('click', '.dropdown-menu', function (e) {
if ($(this).children('.dropdown-menu').length > 0) {
e.stopPropagation();
}
});
// This fixes the problem that the parameter menu collapses
$(document).on('click tab', '.paraMenu li a', function (e) {
if ($(this).hasClass('dropdown-toggle')) {
// ===================== When there is clicked in parameter menu, keep the menu open ======================
$(this).closest('.top-menu-icon.vi').addClass('open');
// keep all parents li open aswell
$(this).parents('li.dropdown').addClass('open');
}
});
// This fixes the problem that the main sub-menu collapses
$(document).on('click tap', '.dropdown-menu li a', function (e) {
if ($(this).parents().hasClass('dropdown-submenu')) {
// ===================== When there is clicked in the sub menu, keep the menu open ======================
$(this).parents('.dropdown-menu').addClass('open');
$(this).parents('li.dropdown').addClass('open');
}
});
//$('.icon-tooltip').tooltip();
if ($('.head-brand .dropdown-menu').length > 0) {
new PerfectScrollbar('.head-brand .dropdown-menu');
}
$('a[data-toggle=tooltip]').each(function () {
$(this).tooltip();
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-FullTable' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'FullTable';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-Basic' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'Basic';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-VeryBasic' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'VeryBasic';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-VeryBasicLink' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'VeryBasicLink';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-Docs' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'Docs';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-input' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'Input';
config.height = 32;
config.autoParagraph = false;
config.enterMode = CKEDITOR.ENTER_BR;
config.shiftEnterMode = CKEDITOR.ENTER_BR;
config.bodyClass = "ckeditor-input";
config.extraPlugins = 'autogrow';
config.autoGrow_minHeight = 0;
config.autoGrow_maxHeight = 600;
config.autoGrow_bottomSpace = 0;
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-inputNB' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'InputNB';
config.height = 32;
config.autoParagraph = false;
config.enterMode = CKEDITOR.ENTER_BR;
config.shiftEnterMode = CKEDITOR.ENTER_BR;
config.bodyClass = "ckeditor-input";
config.extraPlugins = 'autogrow';
config.autoGrow_minHeight = 0;
config.autoGrow_maxHeight = 600;
config.autoGrow_bottomSpace = 0;
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-html' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'Full';
config.height = 32;
config.autoParagraph = false;
config.enterMode = CKEDITOR.ENTER_BR;
config.shiftEnterMode = CKEDITOR.ENTER_BR;
config.bodyClass = "ckeditor-input";
config.extraPlugins = 'autogrow';
config.autoGrow_minHeight = 250;
config.autoGrow_maxHeight = 600;
config.autoGrow_bottomSpace = 0;
config.autoGrow_onStartup = true;
config.allowedContent = true;
config.removeFormatAttributes = '';
config.extraAllowedContent = '*(*);*{*}';
});
CKEDITOR.on('instanceReady', function (ev) {
//catch ctrl+clicks on 's in edit mode to open hrefs in new tab/window
$(this).find('iframe').contents().click(function (e) {
if (typeof e.target.href !== 'undefined' && e.ctrlKey === true) {
window.open(e.target.href, 'new' + e.screenX);
}
});
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-message' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'Message';
});
CKEDITOR.replaceAll(function (textarea, config) {
var classRegex = new RegExp('(?:^| )' + 'ckeditor-messageNoDefaultTexts' + '(?:$| )');
if (!classRegex.test(textarea.className)) {
return false;
}
config.toolbar = 'MessageNoDefaultTexts';
});
/**
* On click input FileType delete
*/
$('.input-file-delete').on('click', function () {
var id = $(this).data('id');
bootbox.confirm(jData.clng.show('areyousure'), function (result) {
if (result) {
$('#' + id + '-div').hide();
$('#delete-' + id).val('1');
$('#stored-' + id).val('');
}
});
});
/**
* Make color input change the color picker
*/
$('body').find('.colorPickerInput').off('keyup blur').on('keyup blur', function () {
var id = $(this).data('color-picker-input-id');
var name = $(this).data('color-picker-input-name');
var colorType = $(this).data('color-picker-input-color-type');
jData.colorType.changeColor(id, name, colorType);
});
/*$('body').find('.colorPickerInput').on('click', function () {
var id = $(this).data('color-picker-input-id');
$('#colorPickerInputBox_' + id).trigger("colorpickersliders.show");
});
$('body').find('.colorPickerInput').on('blur', function () {
var id = $(this).data('color-picker-input-id');
$('#colorPickerInputBox_' + id).trigger("colorpickersliders.hide");
});*/
});
function inputMenuSelected(id, name, value, originalSelected) {
$('#inputMenuText' + name + id).html(value.name + " ");
$('#inputMenuInput' + name + id).val(value.id);
if (originalSelected == "") {
$('.inputMenuDropDown' + name + id + ' li').each(function () {
$(this).removeClass("active");
});
$('#inputMenuItem' + name + id + value.id).addClass("active");
}
}
$(document).on('click', 'a.typeaheadMenu', function () {
var inputId = $(this).data('inputid');
var typeaheadSource = $(this).data('source');
var typeaheadSelectedId = $(this).data('selectedid');
var typeaheadSelectedName = $(this).data('selectedname');
$(this).hide();
var typeAheadContainer = $('.typeaheadMenuTypeaheadContainer' + inputId);
typeAheadContainer.show();
if (typeaheadSelectedId > 0) {
$('#typeaheadMenuTypeahead' + inputId).append($(''));
}
select2Typeahead('typeaheadMenuTypeahead' + inputId, typeaheadSource, typeaheadSelectedId, typeaheadSelectedName);
});
$(document).on('change changeSelection', '.typeaheadMenuTypeahead', function () {
var inputId = $(this).data('inputid');
var selectedItemId = $(this).val();
var selectedItemName = getTypeaheadText('typeaheadMenuTypeahead' + inputId);
if (selectedItemName != "") {
$(this).select2('destroy');
$('.typeaheadMenuTypeaheadContainer' + inputId).hide();
$('#typeaheadMenuTypeahead' + inputId).empty();
var typeaheadMenuTextElement = $('#typeaheadMenuText' + inputId);
if (selectedItemName == "") {
typeaheadMenuTextElement.text(jData.clng.show("none"));
} else {
typeaheadMenuTextElement.text(selectedItemName);
}
if (selectedItemId == "") {
selectedItemId = 0;
}
typeaheadMenuTextElement.data('selectedid', selectedItemId);
typeaheadMenuTextElement.data('selectedname', selectedItemName);
typeaheadMenuTextElement.show();
if (typeaheadMenuTextElement.hasClass('shorten')) {
typeaheadMenuShorten(inputId);
}
$('#typeaheadMenuInput' + inputId).val(selectedItemId);
typeaheadMenuCallback(inputId, selectedItemId, selectedItemName);
}
});
$(document).on('click', '.typeaheadMenuClose', function () {
var inputId = $(this).data('inputid');
var typeaheadMenuTextElement = $('#typeaheadMenuText' + inputId);
$('#typeaheadMenuTypeahead' + inputId).empty().select2('destroy');
$('.typeaheadMenuTypeaheadContainer' + inputId).hide();
typeaheadMenuTextElement.show();
if (typeaheadMenuTextElement.hasClass('shorten')) {
typeaheadMenuShorten(inputId);
}
typeaheadMenuCallback(inputId, typeaheadMenuTextElement.data('selectedid'), typeaheadMenuTextElement.data('selectedname'));
});
function typeaheadMenuShorten(inputId) {
var typeaheadMenuTextElement = $('#typeaheadMenuText' + inputId);
var textElement = "";
textElement += typeaheadMenuTextElement.data("selectedname");
textElement += " ";
typeaheadMenuTextElement.remove();
$('#typeaheadMenuInput' + inputId).after(textElement);
$('#typeaheadMenuText' + inputId).shorten({
"showChars": 25,
"moreText": jData.clng.show("moreText"),
"lessText": jData.clng.show("lessText")
});
}
function typeaheadMenuCallback(inputId, selectedId, selectedName) {
var functionName = $('#typeaheadMenuText' + inputId).data("functionname");
try {
if (functionName != "") {
window[functionName](inputId, selectedId, selectedName);
}
} catch (e) {
console.log("typeaheadMenu - function does not exist: " + functionName);
}
}
function getTypeaheadText(name) {
return $('#select2-' + name + '-container')
.contents()
.filter(function () {
return this.nodeType == Node.TEXT_NODE;
})
.text();
}
/**
* Clear browser cache (contains datatable filters)
*/
function clearLocalstorage() {
lscache.flush();
localStorage.clear();
}
/**
* Function gets active filters span elements, iterete over them
* and create array of filterName => filterValue
*
* @param {string} tableName
*/
function getActiveDataTableFilters(tableName) {
let activeFiltersElement = $('.filters-info-' + tableName).children('span');
let activeFilters = [];
$.each(activeFiltersElement, function (index, element) {
// Get filter name from text content and remove two last characters that are whitespace x
let filterName = element.textContent.slice(0, -2);
// Add it to activeFilters array, original title is value of filter
activeFilters[filterName] = element['dataset'].originalTitle;
});
return activeFilters;
}
/**
* Check if local storage is still valid. We clear the local storage every major release.
*
* @param {string} puntooVersion
*/
function checkStorageValid(puntooVersion) {
// Only get the major from the puntoo version
const puntooMajorVersion = parseFloat(puntooVersion.split('.').slice(0, 2).join('.'));
// skip invalid versions
if (isNaN(puntooMajorVersion) || puntooMajorVersion <= 0) {
return;
}
if (lscache.get('puntooMajorVersion') !== puntooMajorVersion) {
clearLocalstorage();
lscache.set('puntooMajorVersion', puntooMajorVersion);
}
}
/**
* For replacing all the input fields in a form
*/
function setupToOnlyRead() {
$.each($("form input"), function () {
var thisObject = $(this);
if (thisObject.prop("type") != "hidden") {
thisObject.attr("disabled", true);
}
});
$.each($("form select"), function () {
var thisObject = $(this);
thisObject.attr("disabled", true);
});
$.each($("form textarea"), function () {
var thisObject = $(this);
thisObject.attr("disabled", true);
});
$(".form-actions .btn-primary").remove();
}
/**
* Function to disable form actions and extra action buttons
*/
function disableFormActions() {
$(".extra-form-action").hide();
$(".form-actions .btn").hide();
$(".form-actions a.btn-loader").show();
}
/**
* Function to enable form actions and extra action buttons
*/
function enableFormActions() {
$(".extra-form-action").show();
$(".form-actions .btn").show();
$(".form-actions a.btn-loader").hide();
}
/**
* Function to show a loader spinner in the header column from a datatable
*/
function showActionLoader(showHide) {
if (void 0 == showHide) showHide = false;
if (showHide) {
if (typeof $("#actionLoader") == "undefined" || $("#actionLoader").length == 0)
$("th.table-action-col:first .btn-group").append("");
} else {
$("#actionLoader").remove();
}
}
/**
* Function to show all form buttons as warning when change took place
*/
function warningChangedForm() {
$(".form-actions .btn-primary:visible").removeClass("btn-primary").addClass("btn-warning");
$('.hide-on-warning-changed-form').hide();
}
$(function () {
$("body").on("change changeSelection", ".checkFormChanged", function () {
if ($(this).hasClass('input-date') || $(this).hasClass('input-time')) {
// ? Skip form change events for date and time inputs. They both trigger a change on load.
// ? capture Date change with .datepicker().on('changeDate', function () {});
// ? and Time change with .timepicker().on('changeTime.timepicker', function () {});
// ? Be careful redefining the pickers.
return;
}
warningChangedForm();
});
// ? Loop all ckeditor instances to check if original textarea has the checkFormChanged class.
// Timout required to initialize instances after replaceAll
setTimeout(function () {
for (let i in CKEDITOR.instances) {
(function (i) {
CKEDITOR.instances[i].on('change', function () {
let hasFormChanged = $('textarea[id="' + CKEDITOR.instances[i].name + '"]').hasClass('checkFormChanged');
if (hasFormChanged) {
warningChangedForm();
}
});
})(i);
}
}, 0);
// ? Capture date change event, this one is not forced on initialisation.
$("body").on("changeDate", ".checkFormChanged.input-date", function () {
warningChangedForm();
});
// ! New version of timePicker required this is already triggered on init.
// $("body").on("changeTime.timepicker", ".checkFormChanged.input-time", function () {
// warningChangedForm();
// });
// Show warning for changed content tab and ask to send form when other tab is opened
$('body').on('click', '.tabContentChanged', function () {
checkTabsSaved();
});
});
/**
* Check if all tabs are saved.
*
* @returns {boolean}
*/
function checkTabsSaved() {
var result = true;
// Check for changed content on other tabs with this class
$('.tabContentChanged').each(function (index) {
// Can only change one tab at the same time
var tabHref = $(this).find('a').attr('href');
// Default show confirmation BootBox to save tab
var isConfirm = true;
if (typeof $(this).data('confirm') !== 'undefined' && $(this).data('confirm') === 'off') {
isConfirm = false;
}
// Check if icon was already added
var hasIcon = $(this).find('a .fa-exclamation-circle').length > 0;
if (hasIcon) {
result = false;
} else if (!hasIcon && $(tabHref).find('.form-actions .btn-warning').length !== 0) {
result = false;
// Add icon
$(this).find('a').append(' ');
if (isConfirm) {
// Ask question to save previous tab
bootbox.confirm(jData.clng.show('save_previous_unsaved_tab'), function (result) {
if (result) {
// Submit form
$('[href="' + tabHref + '"]').tab('show');
// Click first save button
$(tabHref).find('form').find('input[type="submit"]:nth-child(1)').trigger('click');
}
});
}
}
});
return result;
}
/**
* Multiselect Ajax
*
* @type {{init: jData.multiSelectAjax.init, typeAheadSelect: jData.multiSelectAjax.typeAheadSelect, addRow: jData.multiSelectAjax.addRow, removeRow: jData.multiSelectAjax.removeRow, refreshSelectedAmount: jData.multiSelectAjax.refreshSelectedAmount, setInputData: jData.multiSelectAjax.setInputData, getInputData: jData.multiSelectAjax.getInputData}}
*/
jData.multiSelectAjax = function (id, source, useDynamicUrl, changeCallback, width) {
window["multiSelectAjax-" + id] = this;
this.ElementId = id;
this.source = source;
this.changeCallback = changeCallback;
this.selectedList = {};
this.selectedAmount = 0;
// If a function as string is passed, we use dynamic urls
if (typeof useDynamicUrl !== "string") {
this.useDynamicUrl = false;
} else {
this.useDynamicUrl = useDynamicUrl;
}
this.selectedList = {};
this.selectedAmount = 0;
this.width = typeof width === 'undefined' ? '' : width;
// Set the return function
jData.returnFunction["multiselectAjax-" + id] = this;
// Create the typeahead
select2Typeahead(id + "-typeAhead", source, 0, "", "multiselectAjax-" + id, this.useDynamicUrl, width);
// Create the perfect scrollbar
this.scrollbar = new PerfectScrollbar(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-table-container", {suppressScrollX: true});
// Initialize
this.getInputData();
this.refreshSelectedAmount();
// Check or the select is disabled. if disabled then we add a prop to the multi select container to indicate it is disabled
if ($('#' + id + '-typeAhead').prop('disabled') == true) {
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-container").attr('data-disabled', true).prop('data-disabled', true);
}
// Listener for when removeAll is clicked
$(".multiselectAjax-" + this.ElementId + " .dt-" + this.ElementId + "-removeall").click(function () {
if ($(this).closest('div.multiselect-ajax-container').data('disabled') != true) {
window["multiSelectAjax-" + $(this).data("element")].removeAll();
}
});
// Set the placeholder
$(".multiselectAjax-" + this.ElementId + " .select2-selection__placeholder").html(''); // jData.clng.show("dt_select")
// Listener for when the amount selected is clicked. used to open or close the list
$(".multiselectAjax-" + this.ElementId + " .multiselect-selected-amount").click(function () {
$(".multiselectAjax-" + $(this).data("element") + " .multiselect-ajax-table-container").slideToggle("slow");
});
};
jData.multiSelectAjax.prototype.typeAheadSelect = function (item) {
if (item.id > 0 || (typeof item.id === 'string' && item.id.length > 0)) {
this.addRow(item.id, item.name);
// Reset the typeahead selection
if ($("#" + this.ElementId + "-typeAhead").data('select2')) {
clearTypeahead(this.ElementId + "-typeAhead");
}
}
};
jData.multiSelectAjax.prototype.addRow = function (id, name, force) {
if (!this.selectedList[id] || force) {
/**
* Check if there is a changeCallback function. Execute this when it exist.
* The add() function has to be called, from within the changeCalllback.
*/
if (this.changeCallback) {
window[this.changeCallback](this, 'add', id, force, name);
return false;
}
this.add(id, name, force);
}
};
jData.multiSelectAjax.prototype.add = function (id, name, force) {
// Add the line
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-table").append('
' + name + '
');
// Initialize the variable if empty
if (this.selectedList.length == 0) {
this.selectedList = {};
}
// Add the element
this.selectedList[id] = name;
this.setInputData();
this.refreshSelectedAmount();
// Add a listener to the row to delete the current line when clicking on the times of the line
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-table .selected-" + id + " .selected-delete").click(function () {
if ($(this).closest('div.multiselect-ajax-container').data('disabled') != true) {
window["multiSelectAjax-" + $(this).data("element")].removeRow($(this).data("id"));
}
});
// Add a listener to the row to delete the current line when double clicking on the line
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-table .selected-" + id + "").dblclick(function () {
if ($(this).closest('div.multiselect-ajax-container').data('disabled') != true) {
window["multiSelectAjax-" + $(this).find('.selected-delete').data("element")].removeRow($(this).find('.selected-delete').data("id"));
}
});
// Trigger change
if (!force) {
$("#" + this.ElementId + "-data").trigger("selectChange");
this.scrollbar.update();
}
};
jData.multiSelectAjax.prototype.removeRow = function (id, force) {
/**
* Check if there is a changeCallback function. Execute this when it exist.
* The remove() function has to be called, from within the changeCalllback.
*/
if (this.changeCallback) {
window[this.changeCallback](this, 'remove', id, force);
return false;
}
this.remove(id, force);
};
jData.multiSelectAjax.prototype.remove = function (id, force) {
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-table .selected-" + id + "").remove();
delete this.selectedList[id];
this.setInputData();
this.refreshSelectedAmount();
//Trigger change
if (!force) {
$("#" + this.ElementId + "-data").trigger("selectChange");
this.scrollbar.update();
}
};
jData.multiSelectAjax.prototype.removeAll = function () {
var thisElement = this;
$.each(this.selectedList, function (index, item) {
thisElement.removeRow(index, true);
});
this.refreshSelectedAmount();
$('#' + this.ElementId + '-typeAhead').empty();
$("#" + this.ElementId + "-data").trigger("selectChange");
};
jData.multiSelectAjax.prototype.refreshSelectedAmount = function () {
var selectedAmount = 0;
$.each(this.selectedList, function (index, item) {
selectedAmount = selectedAmount + 1;
});
this.selectedAmount = selectedAmount;
$(".multiselectAjax-" + this.ElementId + " .multiselect-selected-amount").html(jData.clng.show("dt_selected", this.selectedAmount));
};
jData.multiSelectAjax.prototype.setInputData = function () {
var jsonData = JSON.stringify(this.selectedList);
$("#" + this.ElementId + "-data").val(jsonData);
};
jData.multiSelectAjax.prototype.getInputData = function () {
this.selectedList = {};
var jsonData = $("#" + this.ElementId + "-data").val();
if (jsonData !== "") {
this.selectedList = JSON.parse(jsonData);
for (var index in this.selectedList) {
this.addRow(index, this.selectedList[index], true);
}
}
};
jData.multiSelectAjax.prototype.getSelectedList = function () {
return this.selectedList;
};
jData.multiSelectAjax.prototype.getSelectedJSON = function () {
return JSON.stringify(this.selectedList);
};
jData.multiSelectAjax.prototype.getSimpleSelected = function () {
var selectedList = this.selectedList;
var res = [];
Object.keys(selectedList).forEach(function (key) {
res.push(key);
});
return res.join(",");
};
/**
* @param {Object} list
*/
jData.multiSelectAjax.prototype.setSelectedList = function (list) {
if (list !== null && list !== "") {
this.selectedList = list;
this.setInputData();
this.getInputData();
}
};
jData.multiSelectAjax.prototype.setSelectedJSON = function (jsonData) {
if (jsonData !== null && jsonData !== "") {
this.selectedList = JSON.parse(jsonData);
this.setInputData();
this.getInputData();
}
};
jData.multiSelectAjax.prototype.hasSelection = function () {
return this.selectedAmount > 0;
};
// Function to enable the multi select ajax
jData.multiSelectAjax.prototype.enable = function () {
$("#" + this.ElementId + "-typeAhead").prop('disabled', false).attr('disabled', false);
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-container").prop('data-disabled', false).attr('data-disabled', false);
};
// Function to disable the multi select ajax
jData.multiSelectAjax.prototype.disable = function () {
$("#" + this.ElementId + "-typeAhead").attr('disabled', true).prop('disabled', true);
$(".multiselectAjax-" + this.ElementId + " .multiselect-ajax-container").attr('data-disabled', true).prop('data-disabled', true);
};
/**
* Update the source for multiSelectAjax
* @param {string} newSource
*/
jData.multiSelectAjax.prototype.setSource = function (newSource) {
this.removeAll();
let typeaheadId = this.ElementId + '-typeAhead';
clearTypeahead(typeaheadId);
select2Typeahead(typeaheadId, newSource, 0, '', "multiselectAjax-" + this.ElementId);
}
String.prototype.capitalizeFirstLetter = function () {
return this.charAt(0).toUpperCase() + this.slice(1);
};
jData.telephoneExchange = [];
/**
* Do a call with the url. If a function has been given return the data and responseCode
*
* Name and id is used for an unique field. If you want to add a class to a field.
*
* @param name A name
* @param id An id
* @param api The config api value
* @param url The url to call to
* @param callbackFunction The callback function. If this is not an empty string it will call the function
* with the following parameters:
* 1) name => The name from the dial parameter
* 2) id => The id from the dial parameter
* 3) data => The response text from the url
* 4) responseCode => 1 if success, 2 if failed because of an invalid number, 3 failed because of an unknown reason
*/
jData.telephoneExchange.dial = function telephoneExchangeDial(name, id, api, url, callbackFunction) {
switch (api) {
case "1": // Lentrix
if (url != "") {
url = url.replace("+", "%2B");
$.ajax({
type: "POST",
dataType: "html",
url: url,
data: {},
success: function (data) {
if (callbackFunction != "") {
var responseCode;
if (data.indexOf("Dialing") != -1) { // Success
responseCode = 1;
} else if (data.indexOf("Unable to determine number") != -1) { // Failed (invalid number)
responseCode = 2;
} else { // Failed (unknown)
responseCode = 3;
}
callbackFunction(name, id, api, data, responseCode);
}
}
});
}
break;
default:
break;
}
};
// ===================== FILE UPLOADER INPUT FUNCTIONS =====================
/**
* Create a file uploader input listener
*
* @param id A unique id
* @param name A unique name
*/
function createFileUploaderInputListener(id, name) {
$('.fileUploaderInputListener').on('change', ".fileUploaderInput[data-id='" + id + "'][data-name='" + name + "']", function (e) {
var fileSize = this.files[0].size;
var element = $(this);
var elementId = element.data('id');
var elementName = element.data('name');
var elementIndex = element.data('index');
var nextIndex = parseInt(elementIndex) + 1;
var fileName = element.val();
var elementClass = element.attr('class');
$('#' + elementId + "_" + elementName + "_list").append("
");
$('#' + elementId + "_" + elementName + "_container").prepend("");
element.hide();
});
}
/**
* Delete the input element
*
* @param elementId The element id
* @param elementName The element name
* @param elementIndex The element index
*/
function deleteFileInputElement(elementId, elementName, elementIndex) {
$('.fileUploaderInput[data-index="' + elementIndex + '"][data-id="' + elementId + '"][data-name="' + elementName + '"]').remove();
$('#' + elementId + "_" + elementName + "_list_" + elementIndex).remove();
}
/**
* Reset the file input
*
* @param elementId The element id
* @param elementName The element name
*/
function resetFileInput(elementId, elementName) {
var container = $('#' + elementId + "_" + elementName + "_container");
$('#' + elementId + "_" + elementName + "_list").empty();
var nextIndex = 0;
var elementClass = container.attr('class');
container.empty().append("");
}
/**
* Show the human readable file size
*
* @param B The file size
* @param i The bits
* @returns {string}
*/
function humanFileSize(B, i) {
var e = i ? 1e3 : 1024;
if (Math.abs(B) < e) return B + " B";
var a = i ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] : ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
t = -1;
do B /= e, ++t; while (Math.abs(B) >= e && t < a.length - 1);
return B.toFixed(1) + " " + a[t]
}
jData.forms = {
checkValidation: function (id) {
$('#' + id + ' .invalid-tab').removeClass("invalid-tab");
var $myForm = $('#' + id)
var valid = true;
$('#' + id).find(":valid").each(function () {
$(this).parent().parent().removeClass("error");
$(this).parent().find(".help-inline").text("");
});
if (!$myForm[0].checkValidity()) {
$('#' + id).find(":invalid").first().focus();
$('#' + id).find(":invalid").each(function () {
$(this).parent().parent().addClass("error");
$(this).parent().find(".help-inline").text($(this).attr('data-invalid'));
});
valid = false;
}
return valid;
},
validationWarningTab: function (id) {
if ($('#' + id).checkValidity) {
$('#' + id + ' .invalid-tab').removeClass("invalid-tab");
}
$(".main-content").find("#" + id + " input").on('invalid', function (e) {
var tabId = $(this).closest(".tab-pane").attr('id');
$('a[href$="#' + tabId + '"]').addClass('invalid-tab');
});
},
submitNow: function (id) {
console.log("calling");
$('').hide().appendTo($('#' + id)).click().remove();
}
};
/**
* Date Period input
* @param {string} id The date period input
* @param {{validDates}} options The options which can be given
* @type {{create: jData.datePeriod.create, checkValidDateRange: jData.datePeriod.checkValidDateRange}}
*/
jData.datePeriod = {
defaultOptions: {
validDates: false,
showTimes: false
},
options: {},
create: function (id, options) {
$('#' + id[0] + '_' + id[1] + '-dateRange input').each(function () {
$(this).datepicker();
jData.datePeriod.options[id] = $.extend(jData.datePeriod.defaultOptions, options);
var $startDateInput = $('#' + id[0]);
var $endDateInput = $('#' + id[1]);
if (jData.datePeriod.options[id].validDates) {
jData.datePeriod.setStartDate($startDateInput.val(), $endDateInput);
}
if (jData.datePeriod.options[id].validDates) {
jData.datePeriod.setEndDate($endDateInput.val(), $startDateInput);
}
});
$('#' + id[0] + '_' + id[1] + '-dateRange.error input').css({
'color': '#b94a48',
'border': '#b94a48 solid 1px'
});
$('#' + id[0] + '_' + id[1] + '-dateRange.error .add-on').css({
'color': '#b94a48',
'border': '#b94a48 solid 1px',
'background-color': '#f2dede'
});
$('#' + id[0]).on('changeDate', function () {
var $endDateInput = $('#' + id[1]);
jData.datePeriod.checkValidDateRange(this.value, $endDateInput.val(), id, 'start');
if (jData.datePeriod.options[id].validDates) {
jData.datePeriod.setStartDate(this.value, $endDateInput);
}
});
$('#' + id[1]).on('changeDate', function () {
var $startDateInput = $('#' + id[0]);
jData.datePeriod.checkValidDateRange($startDateInput.val(), this.value, id, 'end');
if (jData.datePeriod.options[id].validDates) {
jData.datePeriod.setEndDate(this.value, $startDateInput);
}
});
},
checkValidDateRange: function (startDate, endDate, id, label) {
var firstValue = startDate.split('-');
var secondValue = endDate.split('-');
var firstDate = new Date(firstValue[2] + '-' + firstValue[1] + '-' + firstValue[0]);
var secondDate = new Date(secondValue[2] + '-' + secondValue[1] + '-' + secondValue[0]);
var date_regex = /^(0[1-9]|1\d|2\d|3[01])\-(0[1-9]|1[0-2])\-(19|20)\d{2}$/;
var isValidDate = false;
if (label === 'start') {
if (!(date_regex.test(startDate))) {
$('#' + id[0]).css({'color': '#b94a48', 'border': '#b94a48 solid 1px'});
isValidDate = false;
} else {
$('#' + id[0]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
isValidDate = true;
}
} else {
if (!(date_regex.test(endDate))) {
$('#' + id[1]).css({'color': '#b94a48', 'border': '#b94a48 solid 1px'});
isValidDate = false;
} else {
$('#' + id[1]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
isValidDate = true;
}
}
if (isValidDate === true) {
if (firstDate > secondDate) {
if (label === 'start') {
// $('#'+id+'_start').css({'color':'#b94a48','border':'#b94a48 solid 1px'});
$('#' + id[1]).val(startDate);
$('#' + id[0]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
$('#' + id[1]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
$('#' + id[0] + '_' + id[1] + '-dateRange .add-on').css({
'color': '#555555',
'border': '#cccccc solid 1px',
'background-color': '#eeeeee'
});
} else {
$('#' + id[1]).css({'color': '#b94a48', 'border': '#b94a48 solid 1px'});
}
} else {
$('#' + id[0]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
$('#' + id[1]).css({'color': '#555555', 'border': '#cccccc solid 1px'});
$('#' + id[0] + '_' + id[1] + '-dateRange .add-on').css({
'color': '#555555',
'border': '#cccccc solid 1px',
'background-color': '#eeeeee'
});
}
}
},
setStartDate: function (date, $element) {
$element.datepicker('setStartDate', date);
},
setEndDate: function (date, $element) {
$element.datepicker('setEndDate', date);
}
};
/** @var array Array holding tagsList data */
jData.tagsList = [];
jData.tagsResultList = [];
jData.tagsToken = [];
jData.tagsTypes = {};
/**
* Constructor for tagsType
* @param id
* @param url
* @param prepopulate
* @param canAddNewTag
* @param parametersJSON
*/
jData.tagsType = function (id, url, prepopulate, canAddNewTag, parametersJSON) {
var parameters = JSON.parse(parametersJSON);
// load translations
jData.lng.addModule('tags', 1);
this.id = id;
this.url = url;
//this in _this
var _this = this;
// Set tagsType object so we can address it later.
jData.tagsTypes[this.id] = this;
//create tagsList and tagsResultList for this id
jData.tagsList[this.id] = {};
jData.tagsResultList[this.id] = [];
//get the source url function
var functionSource;
if (parameters['functionSource'] != null) {
functionSource = window[parameters['functionSource']];
} else {
functionSource = function () {
return _this.url;
}
}
//get the resultsFormatter function
var resultsFormatter;
if (parameters['resultsFormatter'] != null) {
resultsFormatter = window[parameters['resultsFormatter']];
} else {
resultsFormatter = function (item) {
var newTagText = '';
if (typeof item.new != 'undefined' && item.new) {
if (canAddNewTag == true) {
newTagText = ' ' + parameters['newTagText'];
return '
' + item.name + newTagText + '
';
}
} else {
return '
' + item.name + newTagText + '
';
}
}
}
//get the tokenFormatter function
var tokenFormatter;
if (parameters['tokenFormatter'] != null) {
tokenFormatter = window[parameters['tokenFormatter']];
} else {
tokenFormatter = function (item) {
return '
' + item.name + '
';
}
}
//create the tokenInput and store it in tagsToken (needed for
// removing new tag or selecting similar tag)
jData.tagsToken[this.id] = $('#' + this.id).tokenInput(function () {
return functionSource()
}, {
theme: 'facebook',
hintText: parameters['hintText'],
noResultsText: parameters['noResultsText'],
searchingText: parameters['searchingText'],
preventDuplicates: true,
tokenLowerCase: jData.cfunc.parseBool(parameters['lowerCaseStr']),
onAdd: function (item) {
// if added tag is new ask user to choose
// one of similar tags or to confirm new one
if (item.new === true) {
_this.getSimilarsModal(item, parameters['tagTable']);
} else {
jData.tagsList[_this.id][item.id] = item.id;
_this.setList();
}
},
onDelete: function (item) {
delete jData.tagsList[_this.id][item.id];
_this.setList();
},
prePopulate: prepopulate,
resultsFormatter: function (item) {
return resultsFormatter(item);
},
tokenFormatter: function (item) {
return tokenFormatter(item);
},
onResult: function (item) {
if (item.length <= 0) {
return null;
}
// new tag is always first in array
var tagNew = item[0];
// onResult is called only for new searches, old ones
// are cached in tokenInput's cache variable which isn't exposed,
// so save results by searched name to avoid data mutation
jData.tagsResultList[_this.id][tagNew.name] = item;
return item;
}
});
};
/**
* Set the list input with the JSON string data for post
*/
jData.tagsType.prototype.setList = function () {
$('#' + this.id + 'List').val(JSON.stringify(jData.tagsList[this.id]));
};
/**
* Sends ajax request to getSimilars file to get
* similar tags and shows similar tags modal
* @param tagItem
* @param tagTable tag table data from parameters
* @param selectedTags array of selected tags
*/
jData.tagsType.prototype.getSimilarsModal = function (tagItem, tagTable) {
// needed to call showSimilarsModal function
var _this = this;
$.ajax({
type: 'POST',
url: jData.urlB.index("tags/ajax/getSimilars", 1),
dataType: "json",
data: {
searchedText: tagItem.name,
table: tagTable['tableName'],
idColumn: tagTable['idField'],
nameColumn: tagTable['nameField']
},
success: function (data) {
if (data['result'] === 'success') {
// show similar tags modal
_this.showSimilarsModal(tagItem, data['similarTags'])
}
}
});
};
/**
* Updates last tag, if only selector is passed then last tag is deleted, if tagId
* and name are passed deletes last tag and insert's tag with passed parameters
*/
jData.tagsType.prototype.updateLastTag = function (selector, name, tagId) {
// find last token in input
var token = selector.find("li[class='token-input-token-facebook']").last();
// if token exists, set name and id
if (token.length) {
// get tokenInputObject from token input field to use
// token input's functions for removing and adding
var input = jData.tagsToken[this.id];
input = $.data(input.get(0), 'tokenInputObject');
input.remove($.data(token.get(0), 'tokeninput'));
// if name and tagId are passed, add new token
if (name !== undefined && tagId !== undefined) {
var newToken = {id: tagId, name: name};
input.add(newToken);
this.setList();
}
// trigger change event on token input
$('#' + this.id).change();
}
this.focusTokenInput();
};
/**
* select the input field for tags after change
*/
jData.tagsType.prototype.focusTokenInput = function () {
// ? select input field
const inputId = this.id;
// ? use timeout so this can be triggered after the change event
setTimeout(function () {
const $tokenInput = $('#token-input-' + inputId);
$tokenInput.blur();
$tokenInput.focus();
}, 500);
}
/**
* Set listeners for modal, this function is called at creation
* of tagsType input field
*/
jData.tagsType.prototype.setModalListeners = function () {
var id = this.id,
tagsModal = $('#' + id + 'Modal'),
self = this,
tagsInput = $('#' + id),
newTag = $('#' + id + 'NewTag'),
itemId = '',
tokenList = tagsModal.siblings('ul.token-input-list-facebook'),
tokenDropdown = $('.token-input-dropdown-facebook');
// event listener when user confirms creation of new tag
tagsModal
.on('click', '.' + id + '-modal-submit-button', function () {
// set value in list
itemId = newTag.val();
jData.tagsList[id][itemId] = itemId;
self.setList();
tagsModal.modal('hide');
self.focusTokenInput();
});
// click on existing tags
tagsModal
.on('click', 'span.' + id + '-existing-tag', function () {
var existingTag = $(this),
tagName = existingTag.data('name'),
tagId = existingTag.data('value');
// bootbox confirmation modal checks if user wants to add existing tag
tagsModal.modal('hide');
jData.box.confirmFunction('existing_tag', tagName, function (confirm) {
if (confirm) {
// update last tag from html and hide modal
self.updateLastTag(tokenList, tagName, tagId, id);
} else {
tagsModal.modal('show');
}
});
});
// cancel or modal dismiss deletes newly added tag
tagsModal
.on('hide.bs.modal', function () {
var $activeElement = $(document.activeElement);
// if last active element, before hiding modal, is cancel or close button (both have data-dismiss) or
// click outside of modal (it is registered as click on body) delete newly added tag
if ($activeElement.is('[data-dismiss], body')) {
self.updateLastTag(tokenList);
// hide dropdown, needs to be done manually
tokenDropdown.hide();
}
})
};
/**
* Builds modal with similar tags and new tag & shows it
*/
jData.tagsType.prototype.showSimilarsModal = function (tagItem, similarTags) {
var tagsModal = $('#' + this.id + 'Modal'),
modalBodyContent = tagsModal.find('div.form-horizontal'),
modalHeader = tagsModal.find('h3').first(),
newTag = $('#' + this.id + 'NewTag'),
tagsHtml = '',
counter = 0;
// empty modal content
modalBodyContent.html('');
// set new tag input and modal question
newTag.val(tagItem.id);
modalHeader.text(jData.lng.show('ayst_add_new_tag', tagItem.name));
// sort similar tags list by substring position in substrings
if (similarTags.length > 1) {
// new tag object is always first in array, take first
// characters to use in sorting
var query = tagItem.name.substring(0, 3).replace(/[\[\].+()]/g, '');
// filter and sort tags list for tags that contain
// query substring
var first = similarTags.filter(function (el) {
return el.name.indexOf(query) !== -1;
}).sort(function (a, b) {
return a.name.indexOf(query) - b.name.indexOf(query)
});
// create array with other similar tags that don't
// contain substring
var rest = similarTags.filter(function (el) {
return el.name.indexOf(query) === -1;
});
// create array with correct sorting by adding
// rest array to first array
sortedTags = first.concat(rest);
} else {
sortedTags = similarTags;
}
// iterate similar tags array and create modal content
for (var i = 0; i < sortedTags.length; i++) {
counter++;
if (counter > 10) {
break
}
// append similar tags list
tagsHtml += '' + sortedTags[i].name + '';
}
// update header for non-existing/existing tags
if (counter === 0) {
modalBodyContent.siblings('h3').text(jData.lng.show('tag_no_similar'));
} else {
modalBodyContent.siblings('h3').text(jData.lng.show('tag_similar_tags'));
}
modalBodyContent.html(tagsHtml);
// show modal
tagsModal.modal('show');
};
/**
* Set values to tagList array
* @param valuesJSON
*/
jData.tagsType.prototype.setValues = function (valuesJSON) {
if (valuesJSON != '' && valuesJSON != '[]') {
var values = JSON.parse(valuesJSON);
jData.tagsList[this.id] = values;
}
};
/** @var array Array holding tokensList data */
jData.tokensList = [];
jData.tokenInputs = [];
/**
* Creates token input on input with id passed as parameter
*
* @param id
* @param url
* @param prePopulate
* @param parametersJSON
*/
jData.tokenType = function (id, url, prePopulate, parametersJSON) {
var parameters = JSON.parse(parametersJSON);
this.id = id;
this.url = url;
//this in _this
var _this = this;
//create tagsList and tagsResultList for this id
jData.tokensList[this.id] = {};
jData.tokenInputs[this.id] = [];
//get the source url function
var functionSource;
if (parameters['functionSource'] != null) {
functionSource = window[parameters['functionSource']];
} else {
functionSource = function () {
return _this.url;
}
}
//get the resultsFormatter function
var resultsFormatter;
if (parameters['resultsFormatter'] != null) {
resultsFormatter = window[parameters['resultsFormatter']];
} else {
resultsFormatter = function (item) {
let newTokenText = '';
if (typeof item.new != 'undefined' && item.new) {
newTokenText = ' ' + parameters['newTokenText'];
return '
' + item.name + newTokenText + '
';
} else {
return '
' + item.name + newTokenText + '
';
}
}
}
// Get the tokenFormatter function
var tokenFormatter;
if (parameters['tokenFormatter'] != null) {
tokenFormatter = window[parameters['tokenFormatter']];
} else {
tokenFormatter = function (item) {
return '
' + item.name + '
';
}
}
// Set onAddCallback function
var onAddCallback;
if (parameters['onAddCallback'] != null) {
onAddCallback = window[parameters['onAddCallback']];
} else {
onAddCallback = function (tokenType, item) {
jData.tokensList[tokenType.id][item.id] = item;
tokenType.setList();
}
}
// get onAddCallbackParams
var onAddCallbackParams;
if (parameters['onAddCallbackParams'] != null) {
onAddCallbackParams = parameters['onAddCallbackParams'];
}
// Fix for InternetExplorer7
// Normally we can replace this with Object.values, but the values method does not work for IE7
const prePopulateValues = Object.keys(prePopulate).map(function (e) {
return prePopulate[e];
});
// Create the tokenInput and store it in tagsToken (needed for
// removing new tag or selecting similar tag)
jData.tokenInputs[this.id] = $('#' + this.id).tokenInput(function () {
return functionSource();
}, {
theme: 'facebook',
hintText: parameters['hintText'],
noResultsText: parameters['noResultsText'],
searchingText: parameters['searchingText'],
preventDuplicates: true,
tokenLowerCase: jData.cfunc.parseBool(parameters['lowerCaseStr']),
onAdd: function (item) {
onAddCallback(_this, item, onAddCallbackParams);
},
onDelete: function (item) {
delete jData.tokensList[_this.id][item.id];
_this.setList();
},
prePopulate: prePopulateValues,
resultsFormatter: function (item) {
return resultsFormatter(item);
},
tokenFormatter: function (item) {
return tokenFormatter(item);
},
onResult: function (item) {
return item;
}
});
this.setValues(prePopulate);
};
/**
* Set value of hidden list input
*/
jData.tokenType.prototype.setList = function () {
if (typeof jData.tokensList[this.id] === 'undefined') {
jData.tokensList[this.id] = {};
}
// Uncomment when we fully support ES6
// let list = {...jData.tokensList[this.id], ...{}};
// Object.keys(list).map((key) => {
// list[key] = list[key].id;
// });
let list = $.extend({}, jData.tokensList[this.id]);
Object.keys(list).map(function (key) {
if (typeof list[key] !== 'undefined') {
return list[key] = list[key].id;
}
});
$('#' + this.id + 'List').val(JSON.stringify(list));
};
/**
* Function set values in tokensList array
* @param values
*/
jData.tokenType.prototype.setValues = function (values) {
jData.tokensList[this.id] = values;
this.setList();
};
/**
* Function adds department users to token input type
*
* @param tokenType token type
* @param item token item
* @param params array of parameters
*/
function onAddUsersCcCallback(tokenType, item, params) {
// Check if item is department
if (item.department) {
addDepartmentUsers(item, params);
return
}
// Check if item is team
if (item.team) {
addTeamUsers(item, params);
return
}
// Item isn't department or team, add user
jData.tokensList[tokenType.id][item.id] = item;
tokenType.setList();
}
/**
* Adding users of selected team to CC or token input
*
* @param {Object} item
* @param {inputId: string, includeSelf: boolean, msgBoxId: string, emailsAsId: boolean} params Parameters
*/
function addTeamUsers(item, params) {
let inputId = params.id;
let includeSelf = params.includeSelf;
let msgBoxId = params.msgBoxId;
let emailsAsId = params.emailsAsId;
let $msgBox = $('#' + msgBoxId);
// Filter empty values out tokensList before assigned to selectedUsers
let selectedUsers = JSON.stringify(jData.tokensList[inputId]);
let tokenInputElement = $('#' + inputId);
// Teams id are passed as 'team_id', because tokenInput checks
// for duplicates with userIds list, get teamId needed for AJAX
var teamId = item.id.split('_')[1];
// Remove team from token input
tokenInputElement.tokenInput('remove', item);
$.ajax({
type: 'POST',
url: jData.urlB.index("users/ajax/getTeamUsersCC", 1),
dataType: "json",
data: {
teamId: teamId,
selectedUsers: selectedUsers,
includeSelf: includeSelf
},
success: function (data) {
$.each(data.extras.users, function (k, v) {
// First check if user is added already
if (typeof jData.tokensList[inputId][v.id] !== 'undefined') {
return; // ? This is equivalent of continue in php
}
// Create id based on emailsAsId parameter
let id = emailsAsId ? v.email : v.id.toString();
// Create token object, team members are internal users
let tokenObject = {
id: id,
name: v.name,
email: v.email,
external: false
};
// Add tokens
tokenInputElement.tokenInput('add', tokenObject);
// Parse id to int
let tokenId = emailsAsId ? v.email : parseInt(v.id);
// Add new tokens to tokensList
jData.tokensList[inputId][tokenId] = tokenObject;
});
// Trigger change event on input need for followers input to set followers
tokenInputElement.change();
},
error: function (context) {
if (context && context.responseJSON && context.responseJSON.msg) {
$msgBox.append(showError(context.responseJSON.msg, 0));
return;
}
$msgBox.append(showError(jData.lng.show('error_ajax_call'), 0));
checkAutoSignOut(true);
}
});
}
/**
* Adding users of selected department to Intern/ExternCC
* or as followers
*
* @param {{}} item
* @param {{includeSelf: (*|boolean), id: string, msgBoxId: string, emailsAsId: (*|boolean)}} params Parameters
*/
function addDepartmentUsers(item, params) {
let inputId = params.id;
let includeSelf = params.includeSelf;
let msgBoxId = params.msgBoxId;
let emailsAsId = params.emailsAsId;
let $msgBox = $('#' + msgBoxId);
// Filter empty values out tokensList before assigned to selectedUsers
let selectedUsers = JSON.stringify(jData.tokensList[inputId]);
let tokenInputElement = $('#' + inputId);
// departments id are passed as 'dep_id', because tokenInput checks
// for duplicates with userIds list, get departmentId needed for AJAX
var departmentId = item.id.split('_')[1];
// remove department from token input
tokenInputElement.tokenInput('remove', item);
$.ajax({
type: 'POST',
url: jData.urlB.index("users/ajax/getDepartmentUsersCC", 1),
dataType: "json",
data: {
departmentId: departmentId,
selectedUsers: selectedUsers,
includeSelf: includeSelf
},
success: function (data) {
if (data && data.users) {
if (data.msg === 'success') {
if (data.users.length > 0) {
$.each(data.users, function (k, v) {
// First check if user is added already
if (typeof jData.tokensList[inputId][v.id] !== 'undefined') {
return; // ? This is equivalent of continue in php
}
// Create id based on emailsAsId parameter
let id = emailsAsId ? v.email : v.id.toString();
// Create token object
let tokenObject = {
id: id,
name: v.name,
email: v.email,
external: parseInt(v.external)
};
// Add tokens
tokenInputElement.tokenInput('add', tokenObject);
// Parse id to int
let tokenId = emailsAsId ? v.email : parseInt(v.id);
// Add new tokens to tokensList
jData.tokensList[inputId][tokenId] = tokenObject;
});
// Trigger change event on input need for followers input to set followers
tokenInputElement.change();
}
} else {
$msgBox.append(showError(jData.lng.show('error_ajax_call'), 0));
}
} else {
$msgBox.append(showError(jData.lng.show('error_ajax_call'), 0));
}
},
error: function (context) {
if (context && context.responseJSON && context.responseJSON.msg) {
$msgBox.append(showError(context.responseJSON.msg, 0));
return;
}
$msgBox.append(showError(jData.lng.show('error_ajax_call'), 0));
checkAutoSignOut(true);
}
});
}
/**
* Color Type Input
* @type {{create: jData.colorType.create, convertStringToRgb: jData.colorType.convertStringToRgb, convertStringToHex: jData.colorType.convertStringToHex, convertStringToHsl: jData.colorType.convertStringToHsl, convertColorToString: jData.colorType.convertColorToString, setColor: jData.colorType.setColor, changeColor: jData.colorType.changeColor}}
*/
jData.colorType = {
create: function (id, placement, title, onchangeFunction) {
var _this = this;
$('#colorPickerInputBox_' + id).ColorPickerSliders({
placement: placement,
title: title,
onchange: function (container, color) {
let $colorPicker = $('#colorPickerInputBox_' + id);
let colorInput = $('#' + id);
if (colorInput.is(':disabled')) {
return;
}
$colorPicker.find('i').css('background-color', color.tiny.toHexString());
var colorType = colorInput.data('color-picker-input-color-type');
var value = _this.convertColorToString(color, colorType);
switch (colorType) {
case 'rgb':
value = _this.convertStringToRgb(value);
break;
case 'hex':
value = _this.convertStringToHex(value);
break;
case 'hsl':
value = _this.convertStringToHsl(value);
break;
default:
value = _this.convertStringToRgb(value);
break;
}
colorInput.val(value).trigger('change');
if (typeof onchangeFunction === 'undefined' || onchangeFunction === null || (typeof onchangeFunction === 'string' && onchangeFunction === '')) {
return;
}
if (typeof onchangeFunction === 'function') {
onchangeFunction(container, color);
return;
}
if (typeof onchangeFunction === 'string') {
window[onchangeFunction](container, color);
}
}
});
},
convertStringToRgb: function (value) {
var colorArray = value.split(',');
var r = 0;
var g = 0;
var b = 0;
if (typeof colorArray[0] !== 'undefined' && colorArray[0] !== '') {
r = colorArray[0];
}
if (typeof colorArray[1] !== 'undefined' && colorArray[1] !== '') {
g = colorArray[1];
}
if (typeof colorArray[2] !== 'undefined' && colorArray[2] !== '') {
b = colorArray[2];
}
value = r + ',' + g + ',' + b;
return value;
},
convertStringToHex: function (value) {
var amountMaxCharacters = 7;
var amountCharacters = value.length;
if (amountCharacters < amountMaxCharacters) {
for (var i = 0; i < (amountMaxCharacters - amountCharacters); i++) {
value = value + '0';
}
}
var newValue = '';
if (value.charAt(0) !== '#') {
value = '#' + value;
}
for (var j = 0; j < amountMaxCharacters; j++) {
newValue += value.charAt(j);
}
return newValue;
},
convertStringToHsl: function (value) {
var colorArray = value.split(',');
var h = 0;
var s = 0;
var l = 0;
if (typeof colorArray[0] !== 'undefined' && colorArray[0] !== '') {
h = colorArray[0];
}
if (typeof colorArray[1] !== 'undefined' && colorArray[1] !== '') {
s = colorArray[1];
}
if (typeof colorArray[2] !== 'undefined' && colorArray[2] !== '') {
l = colorArray[2];
}
value = h + ',' + s + ',' + l;
return value;
},
convertColorToString: function (color, colorType) {
var value = '';
switch (colorType) {
case 'rgb':
value = color.rgba.r + ',' + color.rgba.g + ',' + color.rgba.b;
break;
case 'hex':
value = color.tiny.toHexString();
break;
case 'hsl':
value = color.hsla.h + ',' + color.hsla.s + ',' + color.hsla.l;
break;
default:
value = color.rgba.r + ',' + color.rgba.g + ',' + color.rgba.b;
break;
}
return value;
},
show: function (id) {
var colorBox = $('#colorPickerInputBox_' + id);
colorBox.trigger('colorpickersliders.show');
colorBox.trigger('focus');
},
setColor: function (id, name, value, colorType) {
var color = null;
switch (colorType) {
case 'rgb':
value = this.convertStringToRgb(value);
color = tinycolor('rgb(' + value + ')');
break;
case 'hex':
value = this.convertStringToHex(value);
color = tinycolor(value);
break;
case 'hsl':
value = this.convertStringToHsl(value);
color = tinycolor('hsl(' + value + ')');
break;
default:
value = this.convertStringToRgb(value);
color = tinycolor('rgb(' + value + ')');
break;
}
if (color !== null) {
var colorBox = $('#colorPickerInputBox_' + id);
colorBox.trigger('colorpickersliders.updateColor', color);
colorBox.find('i').css('background-color', color.toHexString());
}
},
changeColor: function (id, name, colorType) {
var element = $('#' + id);
var value = element.val();
var color = null;
switch (colorType) {
case 'rgb':
value = this.convertStringToRgb(value);
color = tinycolor('rgb(' + value + ')');
break;
case 'hex':
value = this.convertStringToHex(value);
color = tinycolor(value);
break;
case 'hsl':
value = this.convertStringToHsl(value);
color = tinycolor('hsl(' + value + ')');
break;
default:
value = this.convertStringToRgb(value);
color = tinycolor('rgb(' + value + ')');
break;
}
if (color !== null) {
var colorBox = $('#colorPickerInputBox_' + id);
colorBox.trigger('colorpickersliders.updateColor', color);
colorBox.find('i').css('background-color', color.toHexString());
}
}
};
/**
* The Checkbox input type
*
* @param {string} inputId The inputId
*
* @return {jData.CheckboxType}
* @constructor
*/
jData.CheckboxType = function (inputId) {
this.$container = null;
var _this = this;
/**
* Load in the object
* - Html selectors are fetched
* - The listeners will be set
*
* @return {jData.CheckboxType}
* @private
*/
this._load = function () {
this._setHtmlSelectors();
this._setListeners();
return this;
};
/**
* Fetches the html selectors so we can work with them inside this class
* @private
*/
this._setHtmlSelectors = function () {
this.$container = $('.checkbox-type-container[data-id="' + inputId + '"]')
};
/**
* Sets the listeners for this checkbox type
* @private
*/
this._setListeners = function () {
// Select all listener
this.$container
.off('click', '.flat-checkbox-action-btn[data-action="all"]')
.on('click', '.flat-checkbox-action-btn[data-action="all"]', function () {
_this.selectAll();
});
// Deselect all listener
this.$container
.off('click', '.flat-checkbox-action-btn[data-action="none"]')
.on('click', '.flat-checkbox-action-btn[data-action="none"]', function () {
_this.deselectAll();
});
};
/**
* Select all the checkboxes
*/
this.selectAll = function () {
this.$container.find('input[type="checkbox"]').prop('checked', true);
};
/**
* Deselect all the checkboxes
*/
this.deselectAll = function () {
this.$container.find('input[type="checkbox"]').prop('checked', false);
};
/**
* Load in the object
*/
return this._load();
};
/**
* Create the checkbox html
*
* @param {string} inputId
* @param {string} optionId
* @param {string} optionName
* @param {boolean} checked If the option is checked
*
* @return {string}
* @private
*/
jData.CheckboxType._createCheckboxHTML = function (inputId, optionId, optionName, checked) {
const checkboxName = `${inputId}[${optionId}]`;
const checkboxId = `${inputId}${optionId}`;
const checkedText = checked ? 'checked' : '';
return `
${optionName}
`;
};
/**
* Add an option to the checkbox
*
* @param {string} inputId The input id
* @param {string} optionId The option id
* @param {string} optionName The option name
* @param {boolean} checked If the option is checked
* @param {string} separator The option separator
*/
jData.CheckboxType.addOption = function (inputId, optionId, optionName, checked, separator) {
const $container = $('.checkbox-type-container[data-id="' + inputId + '"]');
$container.append(jData.CheckboxType._createCheckboxHTML(inputId, optionId, optionName, checked) + separator);
};
/**
* remove the given option id
*
* @param {string} inputId The input id
* @param {string} optionId The option id
* @param {string} separator The option separator
*/
jData.CheckboxType.removeOption = function (inputId, optionId) {
const $container = $('.checkbox-type-container[data-id="' + inputId + '"]');
$container
.find('#' + inputId + optionId)
.closest('.inline-flat-checkbox')
.remove();
};
/**
* Reset the checkbox input with the given options.
* If keep selected is true, if the option we add was selected before,
* it will be kept selected.
*
* @param {string} inputId
* @param {{id: number, name: string}[]} options
* @param {boolean} keepSelected
* @param {string} separator
*/
jData.CheckboxType.reset = function (inputId, options, keepSelected, separator) {
// Get the container selector of this input
const $container = $('.checkbox-type-container[data-id="' + inputId + '"]');
// Get all the checkboxes
const $checkboxes = $container.find('input[type="checkbox"]');
// Get the current selected ids (only if keep selected is true)
const selectedIds = keepSelected ? jData.CheckboxType.getSelectedValues(inputId) : [];
// Remove all the checkboxes
$checkboxes.closest('.inline-flat-checkbox').remove();
// Remove the separators from the container aswell, since they are not inside the input
$container.html($container.html().replace(new RegExp(separator, 'g'), ''));
// Add all the options to the list
for (let i = 0, l = options.length; i < l; i++) {
const option = options[i];
const optionId = option.id.toString();
jData.CheckboxType.addOption(
inputId,
optionId,
option.name,
selectedIds.includes(optionId),
separator,
);
}
};
/**
* Get the selected values from the checkbox type
*
* @param {string} inputId
* @return {*[]}
*/
jData.CheckboxType.getSelectedValues = function (inputId) {
const $container = $('.checkbox-type-container[data-id="' + inputId + '"]');
const $checkboxes = $container.find('input[type="checkbox"]').filter(':checked');
if ($checkboxes.length <= 0) {
return [];
}
const selectedIds = [];
for (let i = 0, l = $checkboxes.length; i < l; i++) {
const checkboxValue = $($checkboxes[i]).attr('id').replace(inputId, '');
selectedIds.push(checkboxValue)
}
return selectedIds;
}
/**
* For creating an easy and simple info pop-up
*
* @param event event object
* @param title Title in the pop-up
* @param content Content of the pop-up
*/
function createTipPopup(event, title, content) {
var tPosX = event.pageX + 10;
var tPosY = event.pageY - 50;
var html = '';
//creating the html block
html += '
';
html += '
';
if (title != undefined) {
html += '
' + title + '
';
}
if (content != undefined) {
html += '
' + content + '
';
}
html += '
';
//remove existing tip-popup
$('#tipPopupHelper').remove();
//add the created tip-popup
$(html).appendTo('body');
$('div#tipPopupHelper').css({'position': 'absolute', 'top': tPosY, 'left': tPosX});
//removing the pop-up when clicking on the close button
$("body").on("click", "#tipPopupHelper .close-popup", function () {
$('#tipPopupHelper').remove();
});
//removing the pop-up when clicking out the pop-up
$(document).on("mouseup", function (e) {
var container = $("#tipPopupHelper");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('#tipPopupHelper').remove();
}
});
};
/**
* For creating a info pop-up with calling an ajax
* You need to send back a 'title' and a 'content'
*
* @param event event object
* @param ajaxLink link for the ajax call
* @param data data that you want to send with the ajax
*/
function createTipPopupAjax(event, ajaxLink, data) {
$.ajax({
type: 'POST',
url: ajaxLink,
dataType: 'json',
data: {data: data},
success: function (data) {
createTipPopup(event, data['title'], data['content']);
}
});
}
/**
* Used to slide the panel content of the given name in or out
*
* @param name -> The div with this name will be slided Up or Down
* @param aToggle -> The given toggle will be rotated 180°
*/
function togglePanelContent(name, aToggle) {
var content = $('.' + name);
var toggleButton = $('#' + aToggle);
if (toggleButton.hasClass('fa-rotate-180')) {
content.slideDown("fast", function () {
});
projectContentShowing = true;
toggleButton.removeClass('fa-rotate-180');
toggleButton.prop('title', jData.clng.show("merge"));
} else {
content.slideUp("fast", function () {
});
projectContentShowing = false;
toggleButton.addClass('fa-rotate-180');
toggleButton.prop('title', jData.clng.show("expand"));
}
}
/**
* Convert the first letter of the text to lower case
*
* @param {string} text the text
* @returns {string}
*/
function lcfirst(text) {
return text.charAt(0).toLowerCase() + text.slice(1);
}
/**
* Convert the first letter of the text to upper case
*
* @param {string} text the text
* @returns {string}
*/
function ucfirst(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
jData.inputs = {
/**
* Use this to read out a form to return the input values
* @param {{}} $form
* @returns {Array}
*/
getFormValues: function ($form) {
var fields = [];
var $inputs = $form.find(':input');
var fieldsToIgnore = [];
$.each($inputs, function (key, value) {
var $thisField = $(this);
if (typeof value.name === 'undefined' || value.name === null || value.name === '') {
return;
}
if ($thisField.parent().hasClass('onoffswitch') && $thisField.attr('type') === 'hidden') {
return;
}
if (value.name.search(/[a-zA-Z0-9_]*-typeAhead$/gm) > -1) {
// This is a typeahead
var dataInputName = value.name.substr(0, value.name.length - 10);
fieldsToIgnore.push(dataInputName + '-data');
fieldsToIgnore.push(dataInputName + '-typeAhead');
fields.push({
name: dataInputName,
value: $form.find(':input[name="' + dataInputName + '-data"]').val()
});
return;
}
var $field = {};
$field.name = value.name;
$field.value = value.value;
const fieldType = $thisField.attr('type');
if (fieldType === 'checkbox') {
$field.value = $thisField.is(':checked');
fields.push($field);
} else if (fieldType === 'radio') {
if ($thisField.is(':checked')) {
fields.push($field);
}
} else if ($thisField.is('textarea') && typeof CKEDITOR.instances[value.name] !== 'undefined') {
$field = {};
$field.name = CKEDITOR.instances[value.name].name;
$field.value = CKEDITOR.instances[value.name].getData();
fields.push($field);
} else {
fields.push($field);
}
});
// If there are no fields to filter we can just return the found fields
if (fieldsToIgnore.length <= 0) {
return fields;
}
// Filter out the fields
var filteredFields = [];
var found = false;
for (var i = 0, inputLength = fields.length; i < inputLength; i++) {
found = false;
for (var j = 0, ignoreLength = fieldsToIgnore.length; j < ignoreLength; j++) {
if (fields[i].name === fieldsToIgnore[j]) {
found = true;
}
}
if (!found) {
filteredFields.push(fields[i]);
}
}
return filteredFields;
},
tooltip: {
get: function (text, settings) {
const tooltipClass = settings?.tooltipClass ?? 'tooltip-info';
const placement = settings?.placement ?? 'right';
const html = settings?.html ?? 'false';
const icon = settings?.icon ?? 'fa-info-circle';
const iconClass = settings?.iconClass ?? 'fa fa-lg';
const asButton = settings?.asButton ?? false;
const trigger = settings?.trigger ?? 'hover';
let extraClass = settings?.extraClass ?? '';
extraClass += asButton ? ' btn' : '';
// Create the html for tooltip
let tooltip = ''
+ ''
+ '';
if (!asButton) {
// Add container to keep it inline with text
tooltip = '' + tooltip + ' ';
}
return tooltip;
},
init: function ($container) {
$container.find('a[data-toggle=tooltip]').each(function () {
$(this).tooltip();
});
},
},
};
/**
* Function to format like php does
* @param number
* @param decimals
* @param dec_point
* @param thousands_sep
*/
function php_number_format(number, decimals, dec_point, thousands_sep) {
// Strip all characters but numerical ones.
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function (n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
/**
* Price formatting function
*
* @param number float
* @param decimals int
* @param removeTrailingZeros bool
*/
function showPrice(number, decimals, removeTrailingZeros) {
if (typeof removeTrailingZeros === 'undefined') {
removeTrailingZeros = true;
}
if (typeof decimals === 'undefined') {
decimals = 2;
}
if (removeTrailingZeros) {
var replace = '0';
replace = replace.repeat(decimals);
return php_number_format(number, decimals, ',', ' ').replace(',' + replace, '');
} else {
return php_number_format(number, decimals, ',', ' ');
}
}
/**
* The popup functions
*
* @type {{fitInScreen: jData.popup.fitInScreen}}
*/
jData.popup = {
/**
* Fit the given element inside the screen
*
* If the element is not visible and you want to change the offset
* You need to pass the offset to this function settings.offset {top, left}
*
* @param {{}} $element The jQuery element selector
* @param {{}} jsEvent The JavaScript onMouseOver|mouseenter event
* @param {Object} settings The settings to fit the item on the screen
* @param {float|int|null} settings.minRight The minimum right side if you want to custom position the block
* @param {Object} settings.offset A custom offset for the element, use this when the element is not visible yet
* @param {float|int} settings.offset.top The top offset
* @param {float|int} settings.offset.left The left offset
* @param {jQuery} settings.container The container which will be used to fit in (default: body)
*/
fitInScreen: function ($element, jsEvent, settings) {
// Check if we have an invalid jQuery selector
// If so we can stop here
if ($element.length <= 0) {
return;
}
// Get the body height
let screenHeight, screenWidth;
if (typeof settings.container !== 'undefined') {
const $container = settings.container;
const containerOffset = $container.offset();
screenHeight = $container.outerHeight(true) + containerOffset.top;
screenWidth = $container.outerWidth(true) + containerOffset.left;
} else {
const $container = $('body');
screenHeight = $container.height();
screenWidth = $container.outerWidth(true);
}
// Get the full height of the element
var elementHeight = $element.outerHeight(true);
var elementWidth = $element.outerWidth(true);
// Get the current offset from the element
var offset = settings?.offset ?? $element.offset();
// Calculate the bottom part of the element
var bottomPosition = elementHeight + offset.top;
var rightPosition = elementWidth + offset.left;
// This will be the new offset for the element
var newOffset = {
top: offset.top,
left: offset.left,
};
// Check if the bottom position is outside the screen
if (bottomPosition > screenHeight) {
// Calculate the amount of pixels we need to move to the top
var moveTop = bottomPosition - screenHeight;
// Add 15 more pixels to the top, so we are not stuck in the browser bottom border
moveTop += 15;
// We now add the offset of that element
newOffset['top'] = offset.top - moveTop;
}
// Check if the right position is outside the screen
if (rightPosition > screenWidth) {
// Calculate the amount of pixels we need to move to the left
var leftOffset;
if (jsEvent.clientX) {
leftOffset = ((typeof settings.minRight !== 'undefined') ? settings.minRight : (offset.left - 20)) - elementWidth;
} else {
leftOffset = offset.left - (rightPosition - screenWidth);
}
// We now add the offset of that element
newOffset['left'] = leftOffset;
}
// If one of the new offsets is set we change the offset of the element
$element.offset(newOffset);
}
};
/**
* Filemanager
*/
jData.fmFunction = [];
jData.urlObj = {};
jData.oWindow = {};
jData.fileManager = {
/**
* Get allowed image extensions
* @returns {string[]}
*/
getImageExtensions: function () {
return ["jpg", "jpeg", "gif", "png", "svg"];
},
/**
* Get the public file path in javascript
*
* @param folder
* @param fileName
* @param appId
* @returns {string}
*/
getFilePath: function (folder, fileName, appId) {
// dataSubfolder declared in functions.php
let path = '/public' + dataSubFolder + 'app' + appId + '/' + folder + '/' + fileName;
// remove trailing slash when fileName or folder are empty
return path.replace(/\/+$/, "");
},
/**
* Wrapper function that calls openServerBrowser
*
* @param obj
* @param url
*/
browseServer: function (obj, url) {
jData.urlObj = obj;
this.openServerBrowser(
dataApps[1] + 'libs/filemanager/index.html?exclusiveFolder=' + url + '&langCode=' + currentLng.toLowerCase(),
screen.width * 0.7,
screen.height * 0.7);
},
/**
* Open filemanager window
*
* @param url
* @param width
* @param height
*/
openServerBrowser: function (url, width, height) {
let iLeft = (screen.width - width) / 2;
let iTop = (screen.height - height) / 2;
let sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes";
sOptions += ",width=" + width;
sOptions += ",height=" + height;
sOptions += ",left=" + iLeft;
sOptions += ",top=" + iTop;
jData.oWindow = window.open(url, "BrowseWindow", sOptions);
},
/**
* Function takes RichFileManager connector url
* and extracts fileName from path, removing main folder from string
*
* @param {string} url
*/
getFileName: function (url) {
// Get path parameter, using +5 from to exclude path= from string
let pathParameter = url.substr(url.indexOf('path=') + 5);
let encodedPathString = pathParameter.substr(0, pathParameter.indexOf('&'));
// Decode Uri encoding
let decodedString = decodeURIComponent(encodedPathString);
let splitPathArray = decodedString.split('/');
// By splicing first two elements main folder is deleted from array, first element is empty string and second is main folder
splitPathArray.splice(0, 2);
// Return full path string without main folder
return splitPathArray.join('/');
},
/**
* Check if given file is an image file
*
* @param fileName
*/
isImageFile: function (fileName) {
// Get file extension
let fileExtension = fileName.split('.').slice(-1).pop();
// Check if it's image extension
return this.getImageExtensions().indexOf(fileExtension) !== -1;
}
};
/**
* Call function in fmFunction array,
* SetUrl is function name called in richFileManager
* through window.opener.SetUrl(previewUrl) so it needs to be outside
* jData.fileManager
*
* @param url
*/
function SetUrl(url) {
// Format path from url
let formatedPath = jData.fileManager.getFileName(url);
// Call function
jData.fmFunction[jData.urlObj](formatedPath);
// Close window
jData.oWindow.close();
// Set oWindow to null
jData.oWindow = null;
}
/**
* The DoubleSelectMultipleType class
*
* @param {string} inputId
* @param {Object} settings
* @param {string|function} settings.onAddCallback
*
* @return {jData.DoubleSelectMultipleType}
* @constructor
*/
jData.DoubleSelectMultipleType = function (inputId, settings) {
this.$container = null;
var _this = this;
/**
* Load in the object
* @return {jData.DoubleSelectMultipleType}
*/
this.load = function () {
this._setHtmlSelectors();
this._setListeners();
return this;
};
/**
* Set the html selectors
* @private
*/
this._setHtmlSelectors = function () {
this.$container = $('.double-select-multiple-type-container[data-id="' + inputId + '"]');
};
/**
* Set the listeners
* @private
*/
this._setListeners = function () {
this.$container.off('click', '.btn-double-select-multiple-type-add').on('click', '.btn-double-select-multiple-type-add', function () {
_this._onAddClickListener();
});
this.$container.off('click', '.btn-double-select-multiple-type-delete').on('click', '.btn-double-select-multiple-type-delete', function () {
_this._onDeleteClickListener();
});
this.$container.closest('form').on('submit', function () {
_this._onFormSubmitListener();
});
};
/**
* The on add click listener
* @private
*/
this._onAddClickListener = function () {
const $enabled = _this.$container.find('.double-select-multiple-type-enabled');
const $notEnabled = _this.$container.find('.double-select-multiple-type-not-enabled');
const $children = $notEnabled.children('option:selected');
function addOption() {
$children.remove().appendTo($enabled);
}
// Check if we have a callback available.
const hasCallback = typeof settings?.onAddCallback === 'function' || typeof settings?.onAddCallback === 'string';
if (!hasCallback) {
addOption();
return;
}
// If it's a string we need to use eval to execute the function.
// When the function returns true we may add the option.
if (typeof settings.onAddCallback === 'string') {
const mayAdd = eval(settings.onAddCallback)($children);
if (mayAdd) {
addOption();
}
return;
}
// We know the callback is a function so we can execute it.
// When the function returns true we may add the option.
const mayAdd = settings.onAddCallback($children);
if (mayAdd) {
addOption();
}
};
/**
* The on delete click listener
* @private
*/
this._onDeleteClickListener = function () {
const $enabled = this.$container.find('.double-select-multiple-type-enabled');
const $notEnabled = this.$container.find('.double-select-multiple-type-not-enabled');
$enabled.children('option:selected').remove().appendTo($notEnabled);
};
/**
* The on form submit listener
* @private
*/
this._onFormSubmitListener = function () {
this.$container.find('.double-select-multiple-type-enabled option').prop('selected', true);
this.$container.find('.double-select-multiple-type-not-enabled option').prop('selected', false);
};
/**
* Load and return the object
*/
return this.load();
}
/**
* Get the selected ids of a double select multiple type
*
* @param {string} inputId
*
* @return {*[]}
*/
jData.DoubleSelectMultipleType.getSelectedIds = function (inputId) {
const input = document.getElementById(inputId);
if (input === null) {
return [];
}
const options = input.options;
const selectedIds = [];
for (let i = 0; i < options.length; i++) {
selectedIds.push(options[i].value);
}
return selectedIds;
};
/**
* Remove the given option by value for the given input
* ? Note: This will remove the option from the selected and not selected inputs
*
* @param {string} inputId
* @param {string|number} optionValue
*/
jData.DoubleSelectMultipleType.removeOptionByValue = function (inputId, optionValue) {
const $container = $('.double-select-multiple-type-container[data-id="' + inputId + '"]');
const $enabledOption = $container.find('.double-select-multiple-type-enabled option[value="' + optionValue + '"]');
const $notEnabledOption = $container.find('.double-select-multiple-type-not-enabled option[value="' + optionValue + '"]');
$enabledOption.remove();
$notEnabledOption.remove();
};
/**
* Reset the options of the double select multiple type
*
* @param {string} inputId
* @param {{id: string|number, name: string}[]} selectedOptions
* @param {{id: string|number, name: string}[]} availableOptions
*/
jData.DoubleSelectMultipleType.reset = function (inputId, selectedOptions, availableOptions) {
const $container = $('.double-select-multiple-type-container[data-id="' + inputId + '"]');
const $selectedInput = $container.find('.double-select-multiple-type-enabled');
const $availableInput = $container.find('.double-select-multiple-type-not-enabled');
$selectedInput.empty();
$availableInput.empty();
for (let i = 0, l = selectedOptions.length; i < l; i++) {
$selectedInput.append('');
}
for (let i = 0, l = availableOptions.length; i < l; i++) {
$availableInput.append('');
}
}
/**
* Functions for open hours input
*/
$(function () {
let $body = $('body');
$body.on('change', '.open-hours-input-weekday-container input[type="checkbox"]', function () {
let $weekdayContainer = $(this).closest('.open-hours-input-weekday-container');
let $timeInputs = $weekdayContainer.find('.open-hours-input-time-input');
let $hideElements = $weekdayContainer.find('.open-hours-input-disabled-hide');
let $closedHideElements = $weekdayContainer.find('.open-hours-input-closed-hide');
let $closedInput = $weekdayContainer.find('.open-hours-input-closed-input');
if ($(this).is(':checked')) {
// Enabled
$timeInputs.removeAttr('disabled');
$hideElements.removeClass('open-hours-input-visibility-hidden');
if ($closedInput.val() > 0) {
// Day is set as CLOSED, hide the times.
$closedHideElements.addClass('open-hours-input-visibility-hidden');
}
} else {
// Disabled
$timeInputs.attr('disabled', '');
$hideElements.addClass('open-hours-input-visibility-hidden');
}
});
$body.on('change', '.open-hours-input-closed-input', function () {
let $weekdayContainer = $(this).closest('.open-hours-input-weekday-container');
let $timeInputs = $weekdayContainer.find('.open-hours-input-time-input');
let $hideElements = $weekdayContainer.find('.open-hours-input-closed-hide');
if ($(this).val() <= 0) {
// Open
$timeInputs.removeAttr('disabled');
$hideElements.removeClass('open-hours-input-visibility-hidden');
} else {
// Closed
$timeInputs.attr('disabled', '');
$hideElements.addClass('open-hours-input-visibility-hidden');
}
});
});
/**
* This is used to get the wanted value out of a date difference
* For example i pass two Date objects and I want the difference in days:
* - Now you can use jData.dateDifference.inDays, which will grant you the;
* @type {{inMonths: (function(*, *): *), inWeeks: (function(*, *): *), inDays: (function(*, *): *), inYears: (function(*, *): *), differenceInDays: (function(*): number), differenceInWeeks: (function(*): number)}}
*/
jData.dateDifference = {
/**
* Returns the number of whole days spanned by the difference
*
* @param {Date} d1
* @param {Date} d2
*
* @return {number}
*/
inDays: function (d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return this.differenceInDays(t2 - t1);
},
/**
* Convert the difference in days
*
* @param {number} difference
*
* @return {number}
*/
differenceInDays: function (difference) {
return Math.floor(difference / 86400000); // 24*3600*1000
},
/**
* Returns the number of whole weeks spanned by the difference
*
* @param {Date} d1
* @param {Date} d2
*
* @return {number}
*/
inWeeks: function (d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return this.differenceInWeeks(t2 - t1);
},
/**
* Convert the difference in weeks
*
* @param {number} difference
*
* @return {number}
*/
differenceInWeeks: function (difference) {
return Math.floor(difference / 604800000); // 24*3600*1000*7
},
/**
* Returns the number of whole months spanned by the difference
*
* @param {Date} d1
* @param {Date} d2
*
* @return {number}
*/
inMonths: function (d1, d2) {
var d1Y = d1.getFullYear();
var d2Y = d2.getFullYear();
var d1M = d1.getMonth();
var d2M = d2.getMonth();
return (d2M + 12 * d2Y) - (d1M + 12 * d1Y);
},
/**
* Returns the number of whole years spanned by the difference
*
* @param {Date} d1
* @param {Date} d2
*
* @return {number}
*/
inYears: function (d1, d2) {
return d2.getFullYear() - d1.getFullYear();
}
}
/**
* Function updates module item typeahead source for
* selected module setting
*
* @param {number} moduleSettingId
* @param {string} moduleItemInputName
* @param {string} extraUrl
*/
function updateModuleItemTypeaheadSource(moduleSettingId, moduleItemInputName, extraUrl) {
// Get module item typeahead
let moduleItemTypeahead = $('#' + moduleItemInputName);
// Proceed if module item typeahead exists
if (moduleItemTypeahead.length > 0) {
if (moduleSettingId > 0) {
$.ajax({
type: 'POST',
url: jData.urlB.index("modulesettings/ajax/getModuleSettingClass", 1),
dataType: "json",
data: {
moduleSettingId: moduleSettingId
},
success: function (data) {
let source = data.extras.moduleSettingClass.source;
if (typeof source !== 'undefined' && source !== '') {
// Clear typeahead
clearTypeahead(moduleItemInputName);
// Create new typeahead on module item input
select2Typeahead(moduleItemInputName, source + extraUrl, '', '');
// Remove disabled attribute
moduleItemTypeahead.removeAttr('disabled');
} else {
// Clear typeahead
clearTypeahead(moduleItemInputName);
// If there's no source, disable module item input
moduleItemTypeahead.attr('disabled', 'true');
}
},
error: function (context) {
if (context && context.responseJSON && context.responseJSON.msg) {
$msgBox.append(showError(context.responseJSON.msg, 0));
return;
}
$msgBox.append(showError(jData.lng.show('error_ajax_call'), 0));
checkAutoSignOut(true);
}
});
} else {
// Clear typeahead
clearTypeahead(moduleItemInputName);
// If there's no module selected, disable module item input
moduleItemTypeahead.attr('disabled', 'true');
}
}
}
/**
* The color helper from Puntoo
*
* @type {{hexToRGB: (function(string): string)}}
*/
jData.ColorHelper = {
/**
* Convert a hex color code into rgb
*
* @param {string} hexColorCode
*
* @return {string} rgb(r, g, b)
*/
hexToRGB: function (hexColorCode) {
let r = 0, g = 0, b = 0;
if (typeof hexColorCode === 'undefined') {
return "rgb(" + +r + "," + +g + "," + +b + ")";
}
if (hexColorCode.charAt(0) === '#') {
hexColorCode = hexColorCode.substr(1);
}
// 3 digits
if (hexColorCode.length === 3) {
r = "0x" + hexColorCode[0] + hexColorCode[0];
g = "0x" + hexColorCode[1] + hexColorCode[1];
b = "0x" + hexColorCode[2] + hexColorCode[2];
}
// 6 digits
else if (hexColorCode.length === 6) {
r = "0x" + hexColorCode[0] + hexColorCode[1];
g = "0x" + hexColorCode[2] + hexColorCode[3];
b = "0x" + hexColorCode[4] + hexColorCode[5];
}
return "rgb(" + +r + "," + +g + "," + +b + ")";
}
};
/**
* Get unique values from array
*
* @param {[]} originalArray
* @returns {*[]}
*/
function getUniqueValuesFromArray(originalArray) {
var result = [];
// Iterate over original array and check if value exists in result array, if not add it to result array
$.each(originalArray, function (i, value) {
if ($.inArray(value, result) == -1) {
result.push(value);
}
});
return result;
}
/**
* Copy text to clipboard using navigator clipboard API
*
* @param {string} textValue Text to copy
*/
function copyTextToClipboard(textValue) {
// Use navigator clipboard API to copy text to clipboard
navigator.clipboard.writeText(textValue);
}
/**
* Copy text as html
*
* @param {string} text
*/
function copyTextAsHtml(text) {
const listener = function (ev) {
ev.preventDefault();
ev.clipboardData.setData('text/html', text);
ev.clipboardData.setData('text/plain', text);
};
document.addEventListener('copy', listener);
document.execCommand('copy');
document.removeEventListener('copy', listener);
}
/**
* Create string of random special characters
*
* @param {number} numberOfChars Number of special characters to return
* @returns {string}
*/
function getRandomSpecialChar(numberOfChars) {
// Special chars string from which return string will be created
var specialChars = '*^@!';
var returnString = '';
for (let i = 0; i < numberOfChars; i++) {
// Multiplying by 7 because there are 7 special chars in string
returnString += specialChars.charAt(Math.floor(Math.random() * 7));
}
return returnString;
}
/**
* Replace url parameter, if it doesn't exist append it to the url
*
* @param {string} baseUrl Url string where replacement of parameter is done
* @param {string} replace Replace key
* @param {string} value Replace value
* @returns {string}
*/
function replaceUrlParameter(baseUrl, replace, value) {
// Create the regex pattern to find the key inside the url
let regexPattern = '/' + replace + '/[^\\/]*';
// Check if we have matches inside the base url if so, we need to replace it, otherwise append it
let matches = baseUrl.match(new RegExp(regexPattern));
if (typeof matches !== 'undefined' && matches !== null && matches.length > 0) {
// Replace the key and value with the new value
baseUrl = baseUrl.replace(new RegExp(regexPattern), '/' + replace + '/' + value);
} else {
// Append the key and value
baseUrl += '/' + replace + '/' + value;
}
return baseUrl;
}
/**
* Removes empty values from array
*
* @param {[]} array
* @returns {*}
*/
function removeEmptyElementsFromArray(array) {
return array.filter(i => i);
}
/**
*
* General function to update page title based on page header
* //TODO: Will be removed when view will be rewritten (setPageTitle)
*
*/
$(function () {
const $pageHeader = $('.page-header > h1:first-child');
if (window.hasOwnProperty('appID') && $pageHeader.length > 0 && jData && jData.apps) {
const pageHeaderText = $pageHeader.text();
const $ticketSubject = $('#ticketSubject.ticket-subject-header span');
if ($ticketSubject.length > 0) {
const ticketSubjectText = $ticketSubject.text();
document.title = jData.apps[appID].nameTranslated + ' - ' + ticketSubjectText;
const $ticketNumber = $('#ticketNumber');
if ($ticketNumber.length > 0) {
document.title += ' (' + $ticketNumber.text() + ')';
}
} else if (pageHeaderText !== '') {
document.title = jData.apps[appID].nameTranslated + ' - ' + pageHeaderText;
}
}
});
/**
* Check for mobile usage
*
* @returns {boolean}
*/
window.mobileCheck = function () {
let check = false;
(function (a) {
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
})(navigator.userAgent || navigator.vendor || window.opera);
return check;
};
/**
* Add token objects to token input with objectCallback
*
* @param {string} tokenInputId
* @param {[]} data
* @param {Function} objectCallback
*/
function addTokenObjects(tokenInputId, data, objectCallback) {
// Iterate over data, add object created from objectCallback
$.each(data, function (index, value) {
$('#' + tokenInputId).tokenInput('add', objectCallback(value));
});
}
$(function () {
$('body').on('click', '#disableAbsence', disableAbsence);
});
/**
* Disable current logged-in user's absence
*/
function disableAbsence() {
$.ajax({
type: 'POST',
url: jData.urlB.index("profiel/ajax/disableAbsence", appID),
dataType: "json",
data: {},
success: () => {
// Remove question from platform bar
$('.out-of-office-message').remove();
location.reload();
},
error: (context) => {
const $body = $('body');
if (context && context.responseJSON && context.responseJSON.message) {
$body.append(showError(context.responseJSON.message, 0, null));
return;
}
$body.append(showError(jData.lng.show('error_ajax_call'), 0, null));
checkAutoSignOut(true);
}
});
}