/**
* A script library to import the javascript / css file on the fly
*
* @author Aby Dahana <abydahana@gmail.com>
* @copyright (c) Aksara Laboratory <https://aksaracms.com>
* @license MIT License
*
* This source file is subject to the MIT license that is bundled with this
* source code in the LICENSE.txt file.
*/
"use strict";
/**
* Mimic user agent
*/
const UA = (window.innerWidth >= 1024 ? 'desktop' : 'mobile');
/**
* Store AJAX promise to prevent multiple request
*/
let xhr;
/**
* Pulse time to dismiss toast
*/
let pulseTime;
/**
* Call your own function to run after AJAX call. Add anywhere to your
* javascript file.
*
* Usage:
* afterCall.push( function() { // Expected code to run });
*/
let afterCall = [];
/**
* Get and set content wrapper's height
*/
let fullHeight = window.innerHeight;
/**
* Buzzer's sound, applied when app enable the action's sound
*/
let successBuzzer = new Audio(config.base_url + 'assets/local/sound/success.mp3');
let failBuzzer = new Audio(config.base_url + 'assets/local/sound/fail.mp3');
let warningBuzzer = new Audio(config.base_url + 'assets/local/sound/alert.mp3');
/**
* Mimic phrase helper
*/
function phrase(phrase) {
if (typeof phrases[phrase] !== 'undefined') {
phrase = phrases[phrase];
} else {
phrase.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
})
}
return phrase;
}
/**
* Go to URL slug
*
* @param string url
* @param object params
*
* @return string
*/
function go_to(path, params) {
let url = window.location.href.split(/[?#]/)[0];
let query_string = {};
$.each(params, function(key, val) {
if (val) {
query_string[key] = val;
}
});
if (Object.keys(query_string).length <= 1) {
query_string = null;
}
return url.replace(/\/$/, '') + (path ? '/' + path : '') + (query_string ? '?' + $.param(query_string) : '');
}
/**
* Get the query string value from url
*
* @param string keyword,
* @param string url
*
* @return string
*/
function get_query_string(keyword, url) {
if (! url) {
// No URL's set, use window location
url = window.location;
} else {
url = new URL(url);
}
// Extract parameter
let params = new URLSearchParams(url.search);
// Get query string value based on given keyword
return params.get(keyword);
}
/**
* Rewrite PHP function to javascript format
*/
function htmlspecialchars(string) {
if (typeof string === 'string') {
string = string.replace(/&/g, "&");
string = string.replace(/"/g, """);
string = string.replace(/'/g, "'");
string = string.replace(/</g, "<");
string = string.replace(/>/g, ">");
}
return string;
}
/**
* Convert HEX color to RGBA
*/
function hex2rgba(hex, alpha) {
let channel;
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
channel = hex.substring(1).split('');
if (channel.length == 3) {
channel = [channel[0], channel[0], channel[1], channel[1], channel[2], channel[2]];
}
channel = '0x' + channel.join('');
return 'rgba(' + [(channel >> 16) & 255, (channel >> 8) & 255, channel & 255].join(',') + ',' + (alpha ? alpha : 1) + ')';
}
throw new Error('Bad Hex');
}
/**
* Convert the RGBA color to HEX
*/
function rgba2hex(rgba) {
if (! rgba) {
rgba = 'rgba(255,255,255,1)';
}
let rgb = rgba.replace(/\s/g, '').match(/^rgba?\((\d+),(\d+),(\d+),?([^,\s)]+)?/i);
let hex = '000000';
if (rgb) {
hex = (rgb[1] | 1 << 8).toString(16).slice(1) + (rgb[2] | 1 << 8).toString(16).slice(1) + (rgb[3] | 1 << 8).toString(16).slice(1);
}
return '#' + hex;
}
/**
* Execute the jQuery script inline the document
*/
function jExec(script) {
return script;
}
/**
* Pop the message up
*/
function throw_exception(code, message, target, redirect) {
if (typeof redirect !== 'undefined' && redirect) {
// Hard redirect to target
return window.location.replace(target);
} else {
// Soft redirect to target
$('<a href="' + target + '" class="--xhr"></a>').appendTo('body').trigger('click').remove();
}
if (! message) {
return false;
}
let color = 'danger';
let icon = 'mdi mdi-emoticon-sad-outline';
if ($.inArray(code, [200, 301]) !== -1) {
color = 'success';
icon = 'mdi mdi-check-circle-outline';
} else if ($.inArray(code, [403, 404]) !== -1) {
color = 'warning';
icon = 'mdi mdi-alert-octagram-outline';
}
// Add twig function
Twig.extendFunction('phrase', function(words, check) {
return (words ? phrase(words.trim()) : '');
});
Twig.extendFunction('truncate', function(string, length, delimeter) {
if (string.length <= length) {
return string
}
return string.slice(0, length) + delimeter
});
let template = Twig.twig({
data: components['core/exception.twig']
});
let content = template.render({
color: color,
icon: icon,
message: message
});
// Remove previous notification
$('[data-bs-dismiss=toast]').trigger('click');
// Pop new notification
$(content).appendTo('body');
// Clear previous timeout
clearTimeout(pulseTime);
// Add timeout
pulseTime = setTimeout(function() {
$('[data-bs-dismiss=toast]').trigger('click');
// Clear previous timeout
clearTimeout(pulseTime);
}, 5000);
}
/**
* Because this website is adopt SPA concept, sometime it's require to
* re-trigger required plugins
*/
function reactivate(individual, ignore_self) {
if (typeof individual === 'undefined') {
individual = [];
}
if (typeof ignore_self === 'undefined') {
ignore_self = false;
}
// Global reactivate trigger
if (! individual.length) {
// Clear previous timeout
clearTimeout(pulseTime);
// Remove previous alert
pulseTime = setTimeout(function() {
$('[data-bs-dismiss=toast]').trigger('click');
// Clear previous timeout
clearTimeout(pulseTime);
}, 5000);
/**
* Update element when viewport is modified
*/
_viewport_modifier();
/**
* Detect if device browser is mobile
*/
if (UA != 'mobile') {
/**
* Focus to first field, expect there's modal open. to trigger focus the field inside modal,
* check the correspondent of shown.bs.modal from the global.min.js
*/
$(':input').blur();
if ($('form[method=POST]:visible').last().find('.autofocus:enabled:visible:first').length) {
$('form[method=POST]:visible').last().find('.autofocus:enabled:visible:first').focus();
} else {
$('form[method=POST]:visible').last().find('input[type=text], textarea').filter(':enabled:visible:first:not(.nofocus)').focus();
}
if ($('body').hasClass('sidebar-collapsed auto-collapse')) {
$('body').removeClass('sidebar-collapsed auto-collapse sidebar-hovered');
}
} else {
$('html').removeClass('overflow-hidden');
$('body').removeClass('sidebar-expanded sidebar-hovered');
}
/**
* Sometime the component need to be resolve when the
* browser window is resized
*/
$(window).on('resize', function() {
_viewport_modifier();
})
.on('scroll', function(e) {
if ($('.navbar').first().next('[role=content]').children('.carousel').length || $('.navbar').first().next('[role=content]').children('.leading').length) {
// Apply navigation menu modification
let element = ($('.navbar').first().next('[role=content]').children('.carousel').length ? $('.navbar').first().next('[role=content]').children('.carousel') : ($('.navbar').first().next('[role=content]').children('.leading').length ? $('.navbar').first().next('[role=content]').children('.leading') : null));
let toe = element.offset().top;
let boe = element.offset().top + element.outerHeight();
let bos = $(window).scrollTop() + $(window).innerHeight();
let tos = $(window).scrollTop();
if ((bos > toe) && (tos < boe) && ! $('body').hasClass('sidebar-expanded')) {
$('.navbar').first().addClass('bg-transparent');
} else {
$('.navbar').first().removeClass('bg-transparent');
}
}
});
/**
* Alert user if they using unstable browser
*/
if ($('input[type=file]').length) {
let agent = navigator.userAgent || navigator.vendor || window.opera;
if (agent.toLowerCase().indexOf('fban') > -1 || agent.toLowerCase().indexOf('fbav') > -1 || agent.toLowerCase().indexOf('instagram') > -1) {
alert(phrase('This browser might experience problems related to file reading permissions on your device.'));
}
}
/**
* Dispose previous autocomplete element
*/
if (typeof $.fn.autocomplete !== 'undefined') {
$('[role=autocomplete]').autocomplete('dispose');
}
/**
* Fix the hidden button that break the radius in button group
*/
if ($('.btn-group').find('.btn:hidden:first').nextAll('.btn:visible:first').length) {
$('.btn-group').find('.btn:hidden:first').nextAll('.btn:visible:first').addClass('rounded-start');
} else {
$('.btn-group').find('.btn').not(':first').removeClass('rounded-start');
}
if ($('.btn-group').find('.btn:hidden:last').prevAll('.btn:visible:first').length) {
$('.btn-group').find('.btn:hidden:last').prevAll('.btn:visible:first').addClass('rounded-end');
} else {
$('.btn-group').find('.btn').not(':last').removeClass('rounded-end');
}
/**
* Disable input autocomplete
*/
$('input, textarea').attr('autocomplete', 'off');
$('input[type=password]').attr('autocomplete', 'new-password');
/**
* Remove the DOM's element that used before
*/
$('.dcalendarpicker, #sortableListsBase, .autocomplete-suggestions, .note-popover').remove();
/**
* Remove previous shown tooltip
*/
$('.tooltip.show').remove();
/**
* Reload tooltip and popover
*/
$('[data-bs-toggle=tooltip]').tooltip();
$('[data-bs-toggle=popover]').popover();
/**
* Close offcanvas
*/
$('[data-bs-dismiss=offcanvas]').trigger('click');
/**
* Make textarea autogrow
*/
$('textarea').each(function() {
$(this).css({
height: (this.scrollHeight > $(this).actual('outerHeight') ? (this.scrollHeight + 2) : $(this).actual('outerHeight')),
overflowY: 'hidden'
});
})
.on('input', function() {
if (! $(this).hasClass('no-resize')) {
this.style.height = 'auto';
this.style.height = (this.scrollHeight + 2) + 'px';
}
});
$('body').on('keyup', '.select2-search__field', function(e) {
if (typeof mCustomScrollbar === 'function') {
$('.select2-results').mCustomScrollbar('update');
}
});
/**
* Triggering mousewheel
*/
$('input[type=number]').bind('DOMMouseScroll mousewheel', function(e) {
$(this).trigger('change');
});
/**
* Trigger stopped carousel to slide
*/
if ($('[data-bs-ride=carousel]').length) {
$('[data-bs-ride=carousel]').carousel();
$('[data-bs-ride=carousel]').bind('slide.bs.carousel');
}
/**
* Stop all video and audio player
*/
/*if (typeof mejs !== 'undefined' && typeof mejs.players !== 'undefined') {
$.each(mejs.players, function(key, val) {
if (typeof val.media !== 'undefined') {
if (typeof val.media.hlsPlayer !== 'undefined') {
val.media.hlsPlayer.stopLoad();
val.media.hlsPlayer.destroy();
}
val.media.remove();
}
});
}*/
/**
* Retrigger fetching parameter of API
*/
if ($('.fetch-parameter').length) {
$('.fetch-parameter').trigger('change');
}
/**
* Load more first click
*/
if ($('.load-more').length) {
$('.load-more').trigger('click');
}
/**
* Check parent item and open if it's link were active
*/
$('.sidebar-menu .nav-item.active').each(function() {
$(this).parents('li').addClass('active is-parent');
$(this).parents('ul').addClass('show').prev('.nav-link').addClass('is-expanded');
});
/**
* Call your own function to run after AJAX call. Add anywhere to your
* javascript file.
*
* Usage:
* afterCall.push( function() { // Expected code to run });
*/
if (typeof afterCall !== 'undefined' && $.isArray(afterCall) && afterCall.length) {
$.each(afterCall, function(key, val) {
if (typeof afterCall[key] === 'function') {
afterCall[key].call();
} else {
afterCall[key];
}
});
}
}
/**
* Select2 plugin
*/
if ($('select[role=select]').length && (! individual.length || individual.includes('select')) && ! ignore_self) {
require.css([
config.base_url + 'assets/select2/select2.min.css',
config.base_url + 'assets/select2/select2-bootstrap-5-theme.min.css',
config.base_url + 'assets/local/css/select2.min.css'
]);
require.js([
config.base_url + 'assets/select2/select2.min.js'
], function() {
$('select[role=select]').each(function() {
if ($(this).next('.select2').length || $(this).hasClass('no-js')) {
return;
}
const config = {
theme: 'bootstrap-5',
width: '100%',
placeholder: $(this).attr('placeholder'),
dropdownParent: $(this).parent(),
minimumResultsForSearch: 10,
templateSelection: function(response) {
if (! $(response.element).data('icon')) {
return response.text
}
return $('<i class="' + $(response.element).data('icon') + '"></i> ' + response.text);
},
templateResult: function(response) {
if (! $(response.element).data('icon')) {
return response.text
}
return $('<i class="' + $(response.element).data('icon') + '"></i> ' + response.text);
}
};
if ($(this).data('relation') || $(this).data('href')) {
config.ajax = {
url: $(this).data('href') ?? $(this).closest('form').attr('action'),
method: 'POST',
dataType: 'json',
data: function(params) {
let query = {
search: params.term,
page: params.page || 1,
method: 'ajax_select',
source: $(this).attr('name'),
selected_list: $(this).val()
};
return query;
}
};
}
$(this).select2(config).on('change', function(e) {
// Remove highlight border
$(e.target).next('.select2-container').find('.select2-selection').removeClass('border-danger');
let autosubmit = $(this).closest('form').attr('data-autosubmit');
if (autosubmit) {
$(this).closest('form').trigger('submit');
}
});
});
});
}
/**
* Load wysiwyg editor plugin
*/
if ($('[role=wysiwyg]').length && (! individual.length || individual.includes('wysiwyg')) && ! ignore_self) {
require.css([
config.base_url + 'assets/summernote/summernote.min.css',
config.base_url + 'assets/local/css/summernote.min.css'
]);
require.js([
config.base_url + 'assets/summernote/summernote.min.js'
], function() {
$('[role=wysiwyg]').each(function() {
if ($(this).attr('disabled') || $(this).attr('readonly')) return;
let context = $(this);
$(this).summernote({
dialogsInBody: true,
dialogsFade: false,
spellCheck: false,
disableDragAndDrop: true,
styleTags: [
{
tag: 'h2',
title: 'Heading'
}, {
tag: 'h3',
title: 'Subheading'
}, {
tag: 'p',
title: 'Normal'
}
],
toolbar: [
['style', ['style', 'bold', 'italic', 'underline']],
['para', ['ul', 'ol']],
(UA !== 'mobile' ? ['insert', ['link', 'table', 'picture', 'video']] : null),
(UA !== 'mobile' ? ['misc', ['clear', 'help']] : null)
],
placeholder: ($(this).attr('placeholder') ? $(this).attr('placeholder') : phrase('Your content goes here...')),
disableResizeEditor: true,
callbacks: {
onDialogShown: function(e) {
$('.modal-dialog').addClass('modal-dialog-centered');
$('.form-control-file').addClass('form-control');
},
onPaste: function (e) {
e.preventDefault();
const bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
const modifiedText = bufferText.replace(/\r?\n/g, '<br>');
document.execCommand('insertHtml', false, modifiedText );
},
onImageUpload: function(image) {
let data = new FormData();
data.append("image", image[0]);
// Upload file
$.ajax({
url: config.base_url + 'xhr/summernote/upload',
contentType: false,
processData: false,
data: data,
method: 'POST',
beforeSend: function() {},
success: function(response) {
context.summernote('insertImage', response.source);
}
});
},
onMediaDelete: function(image) {
// Delete file
$.ajax({
url: config.base_url + 'xhr/summernote/delete',
method: 'POST',
data: {
source: image[0].src
}
});
}
}
});
});
});
}
/**
* Load swiperJS
*/
if ($('.swiper').length && (! individual.length || individual.includes('swiper')) && ! ignore_self) {
require.css([
config.base_url + 'assets/swiper/swiper-bundle.min.css',
config.base_url + 'assets/local/css/swiper.min.css'
]);
require.js([
config.base_url + 'assets/swiper/swiper-bundle.min.js'
], function() {
$('.swiper').each(function() {
let context = $(this),
_unique = Math.floor(Math.random() * 9999),
_autoplay = (1 == context.attr('data-autoplay') || 'true' == context.attr('data-autoplay') ? true : false);
context.addClass('swiper_' + _unique);
if (typeof context.attr('data-pagination') !== 'undefined') {
$('<div class="swiper-pagination swiper-pagination_' + _unique + '"></div>').appendTo(context);
}
if (typeof context.attr('data-navigation') !== 'undefined') {
$('<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>').appendTo(context);
}
if (_autoplay) {
_autoplay = {
delay: (typeof context.attr('data-delay') !== 'undefined' ? parseInt(context.attr('data-delay')) : 3000),
pauseOnMouseEnter: true,
disableOnInteraction: false
};
}
let swiper = new Swiper('.swiper_' + _unique, {
watchSlidesProgress: true,
autoplay: _autoplay,
spaceBetween: (typeof context.attr('data-space-between') !== 'undefined' ? parseInt(context.attr('data-space-between')) : 20),
slidesPerView: (typeof context.attr('data-slide-count') !== 'undefined' ? parseInt(context.attr('data-slide-count')) : 'auto'),
breakpoints: {
640: {
slidesPerView: (typeof context.attr('data-slide-count-sm') !== 'undefined' ? context.attr('data-slide-count-sm') : (typeof context.attr('data-slide-count') !== 'undefined' ? parseInt(context.attr('data-slide-count')) : 'auto')),
spaceBetween: (typeof context.attr('data-space-between') !== 'undefined' ? parseInt(context.attr('data-space-between')) : 20)
},
768: {
slidesPerView: (typeof context.attr('data-slide-count-md') !== 'undefined' ? context.attr('data-slide-count-md') : (typeof context.attr('data-slide-count-sm') !== 'undefined' ? context.attr('data-slide-count-sm') : (typeof context.attr('data-slide-count') !== 'undefined' ? parseInt(context.attr('data-slide-count')) : 'auto'))),
spaceBetween: (typeof context.attr('data-space-between') !== 'undefined' ? parseInt(context.attr('data-space-between')) : 20)
},
1024: {
slidesPerView: (typeof context.attr('data-slide-count-lg') !== 'undefined' ? context.attr('data-slide-count-lg') : (typeof context.attr('data-slide-count-md') !== 'undefined' ? context.attr('data-slide-count-md') : (typeof context.attr('data-slide-count-sm') !== 'undefined' ? context.attr('data-slide-count-sm') : (typeof context.attr('data-slide-count') !== 'undefined' ? parseInt(context.attr('data-slide-count')) : 'auto')))),
spaceBetween: (typeof context.attr('data-space-between') !== 'undefined' ? parseInt(context.attr('data-space-between')) : 20)
},
1280: {
slidesPerView: (typeof context.attr('data-slide-count-xl') !== 'undefined' ? context.attr('data-slide-count-xl') : (typeof context.attr('data-slide-count-lg') !== 'undefined' ? context.attr('data-slide-count-lg') : (typeof context.attr('data-slide-count-md') !== 'undefined' ? context.attr('data-slide-count-md') : (typeof context.attr('data-slide-count-sm') !== 'undefined' ? context.attr('data-slide-count-sm') : (typeof context.attr('data-slide-count') !== 'undefined' ? parseInt(context.attr('data-slide-count')) : 'auto'))))),
spaceBetween: (typeof context.attr('data-space-between') !== 'undefined' ? parseInt(context.attr('data-space-between')) : 20)
}
},
pagination: {
el: '.swiper-pagination_' + _unique,
clickable: true
},
navigation: {
prevEl: '.swiper-button-prev',
nextEl: '.swiper-button-next'
}
});
});
});
}
/**
* Load video player (mediaelement.js)
*/
if ($('[role=videoplayer]').length && (! individual.length || individual.includes('videoplayer')) && ! ignore_self) {
require.css([
config.base_url + 'assets/mediaelement/mediaelement.min.css'
]);
require.js([
config.base_url + 'assets/mediaelement/mediaelement.min.js'
], function() {
$('[role=videoplayer]').each(function() {
$(this).mediaelementplayer({
pauseOtherPlayers: true,
stretching: 'fill',
iconSprite: config.base_url + 'assets/mediaelement/mejs-controls.svg',
success: function(player, node) {
player.pause();
}
})
})
});
}
/**
* Load datetimepicker plugin
*/
if ($('[role=calendar]').length && (! individual.length || individual.includes('calendar')) && ! ignore_self) {
require.css([
config.base_url + 'assets/fullcalendar/fullcalendar.min.css'
]);
require.js([
config.base_url + 'assets/fullcalendar/fullcalendar.min.js'
], function() {
$('[role=calendar]').each(function() {
let context = $(this);
let calendar = new FullCalendar.Calendar(document.getElementById(context.attr('id')), {
timeZone: 'GMT',
slotMinTime: (context.attr('data-start-time') ? context.attr('data-start-time') : '08:00:00'),
slotMaxTime: (context.attr('data-start-time') ? context.attr('data-start-time') : '22:00:00'),
height: fullHeight - (($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0)),
initialView: 'timeGridWeek',
headerToolbar: {
left: 'prev,next',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: {
url: context.attr('data-event-url'),
method: 'POST'
},
selectable: (context.attr('data-crud-url') ? true : false),
select: function(info) {
if (context.attr('data-crud-url')) {
$('<a href="' + context.attr('data-crud-url') + '" class="--modal" data-start="' + info.startStr + '" data-finish="' + info.endStr + '"></a>').appendTo('body').trigger('click').remove();
}
}
});
calendar.render();
});
});
}
/**
* Load money format plugin
*/
if ($('[role=money]').length && (! individual.length || individual.includes('money')) && ! ignore_self) {
require.js([
config.base_url + 'assets/autonumeric/autonumeric.min.js'
], function() {
$('[role=money]').autoNumeric('init', {
vMin: '-999999999.99'
});
$('[role=money]').on('focus', function(e) {
$(this).select();
});
});
}
/**
* Uploader plugin
*/
if ($('[role=uploader]').length && (! individual.length || individual.includes('uploader')) && ! ignore_self) {
$('[role=uploader]').each(function() {
let context = $(this);
let files = [];
try {
files = JSON.parse(context.attr('data-fileuploader-files'));
} catch (e) {}
context.removeAttr('data-fileuploader-files');
if (files) {
$.each(files, function(key, val) {
let extension = val.name.substr((val.name.lastIndexOf('.')));
$('<div class="uploader-list w-100"><div class="row mb-2 align-items-center"><div class="col-2 pe-0"><a href="' + val.url + '" target="_blank" download="' + val.name + '">' + (val.icon ? '<img src="' + val.icon + '" class="img-fluid rounded" style="max-height:32px" />' : '<button type="button" class="btn btn-primary pe-2 ps-2">' + extension + '</button>') + '</a></div><div class="col-10 position-relative"><button type="button" class="btn btn-sm position-absolute end-0 me-2" onclick="jExec($(this).closest(\'.input-group\').find(\'.custom-file-label\').text(($(this).closest(\'.input-group\').find(\'textarea\').length - 1) + \' \' + (($(this).closest(\'.uploader-list\').find(\'textarea\').length - 1) > 1 ? phrase(\'files were chosen\') : phrase(\'file was chosen\'))),$(\'[data-bs-toggle=tooltip]\').tooltip(\'hide\'),$(this).closest(\'.uploader-list\').remove())" data-bs-toggle="tooltip" title="' + phrase('Remove') + '"><i class="mdi mdi-delete text-danger"></i></button><textarea name="' + context.attr('name').replace('[]', '') + '_label[' + val.file + ']" class="form-control form-control-sm" rows="1">' + val.name + '</textarea></div></div></div>').insertBefore(context.closest('.uploader-input'));
});
context.next('.custom-file-label').text(files.length + ' ' + (files.length > 1 ? phrase('files were chosen') : phrase('file was chosen')));
$('[data-bs-toggle=tooltip]').tooltip();
}
context.off('change.uploader');
context.on('change.uploader', function(e) {
// Prevent browser to take place as well
e.preventDefault();
let context = $(this);
if (this.files && this.files[0]) {
let file = this.files[0];
let extension = file.name.substr((file.name.lastIndexOf('.')));
let reader = new FileReader;
if (context.attr('accept') && $.inArray(extension, context.attr('accept').split(',')) === -1) {
return throw_exception(403, phrase('Allowed file type') + ' <b>' + context.attr('accept') + '</b>.');
} else if ((file.size / 1024) > config.max_upload_size) {
return throw_exception(403, file.name + ' ' + phrase('is too large'));
}
reader.readAsDataURL(this.files[0]);
reader.onload = function(response) {
if (! response.target.error) {
if (! context.attr('multiple')) {
// Remove previous selected file for non-multiple input
context.closest('.uploader-input').prev('.uploader-list').remove();
}
$('<div class="uploader-list w-100"><div class="row mb-2 align-items-center"><div class="col-2 pe-0"><a href="' + response.target.result + '" target="_blank" download="' + file.name + '">' + ($.inArray(extension, ['.jpg', '.jpeg', '.png', '.gif']) !== -1 ? '<img src="' + response.target.result + '" class="img-fluid rounded" style="max-height:32px" />' : '<button type="button" class="btn btn-primary pe-2 ps-2">' + extension + '</button>') + '</a></div><div class="col-10 position-relative uploader-file-input"><button type="button" class="btn btn-sm position-absolute end-0 me-2" onclick="jExec($(this).closest(\'.input-group\').find(\'.custom-file-label\').text(($(this).closest(\'.input-group\').find(\'textarea\').length - 1) + \' \' + (($(this).closest(\'.input-group\').find(\'textarea\').length - 1) > 1 ? phrase(\'files were chosen\') : phrase(\'file was chosen\'))),$(\'[data-bs-toggle=tooltip]\').tooltip(\'hide\'),$(this).closest(\'.uploader-list\').remove())" data-bs-toggle="tooltip" title="' + phrase('Remove') + '"><i class="mdi mdi-delete text-danger"></i></button><textarea name="' + context.attr('name').replace('[]', '') + '_label[]" class="form-control form-control-sm" rows="1">' + file.name + '</textarea></div></div></div>').insertBefore(context.closest('.uploader-input'));
context.clone().css('display', 'none').removeAttr('role class id').appendTo(context.closest('.uploader-input').prev('.uploader-list'));
context.next('.custom-file-label').text(context.closest('.input-group').find('textarea').length + ' ' + (context.closest('.input-group').find('textarea').length > 1 ? phrase('files were chosen') : phrase('file was chosen')));
context.val('');
$('[data-bs-toggle=tooltip]').tooltip();
}
};
}
});
});
}
/**
* Checkbox
*/
if ($('input[role=checker]').length && (! individual.length || individual.includes('checker')) && ! ignore_self) {
$('input[role=checker]').each(function() {
let _parent = $(this).attr('data-parent');
if ($(this).closest(_parent).find(':checkbox.checker-children:checked').length) {
$(this).prop('checked', true);
} else {
$(this).prop('checked', false);
}
});
}
/**
* Autocomplete plugin
*/
if ($('[role=autocomplete]').length && (! individual.length || individual.includes('autocomplete')) && ! ignore_self) {
require.js([
config.base_url + 'assets/autocomplete/autocomplete.min.js'
], function() {
$('[role=autocomplete]').each(function() {
let context = jQuery(this);
context.on('input', function(e) {
if (! context.val()) {
context.next('input[type=hidden]').remove()
}
});
context.autocomplete({
serviceUrl: (context.attr('data-href') ? context.attr('data-href') : context.closest('form').attr('action')),
params: {
method: 'autocomplete',
origin: context.attr('name'),
siblings: function() {
let data = {};
$.each(_this.closest('form').find(':input').not('[type=file]').not(_this).serializeArray(), function(key, val) {
data[val.name] = val.value;
});
return JSON.stringify(data);
}
},
minChars: 3,
zIndex: 1056,
appendTo: (_this.data('append-to') ? _this.closest(_this.data('append-to')) : 'body'),
noSuggestionNotice: phrase('Nothing found'),
triggerSelectOnValidInput: false,
onSelect: function(suggestion) {
if (typeof suggestion.target !== 'undefined' && suggestion.target) {
// Create and click the temporary link
$('<a href="' + suggestion.target + '" class="--xhr"></a>').appendTo('body').trigger('click').remove();
} else if (context.closest('form').hasClass('--xhr-form')) {
context.closest('form.--xhr-form').trigger('submit');
} else if (context.hasClass('on-autocomplete-trigger')) {
$('input[data-mask-input=autocomplete]').remove();
$('<input type="hidden" name="' + context.attr('name') + '" value="' + suggestion.value + '" data-mask-input="autocomplete" />').insertAfter(context);
}
if (typeof suggestion.affected_field !== 'undefined') {
$.each(suggestion.affected_field, function(key, val) {
_this.closest('form').find('input[name=' + key + ']').val(val).trigger('change')
})
}
},
onSearchComplete: function(query, suggestion) {
// Additional trigger on search complete
}
});
});
});
}
/**
* Fetch additional file to initialize openlayers map
*/
if ($('[role=map]').length && (! individual.length || individual.includes('map')) && ! ignore_self) {
$('[role=map]').each(function() {
let context = $(this);
require.css([
config.base_url + 'assets/openlayers/ol.min.css',
config.base_url + 'assets/openlayers/ol-geocoder/ol-geocoder.min.css',
config.base_url + 'assets/openlayers/ol-popup/ol-popup.min.css', config.base_url + 'assets/local/css/openlayers.min.css'
]);
require.js([
config.base_url + 'assets/jszip/jszip-utils.min.js',
config.base_url + 'assets/jszip/jszip.min.js',
config.base_url + 'assets/openlayers/ol.min.js',
config.base_url + 'assets/openlayers/ol-geocoder/ol-geocoder.min.js',
config.base_url + 'assets/openlayers/ol-popup/ol-popup.min.js',
config.base_url + 'assets/local/js/openlayers.min.js'
], function() {
openlayers.render(context);
$('.ol-zoom-in, .ol-zoom-out, .ol-zoom-extent button, .ol-track button, .ol-attribution button, .ol-rotate-reset button').tooltip({
placement: 'left'
});
});
});
}
/**
* Fetch additional file to initialize syntax highlighter
*/
if ($('pre code').length && (! individual.length || individual.includes('code')) && ! ignore_self) {
require.css([
config.base_url + 'assets/prism/prism.min.css'
]);
require.js([
config.base_url + 'assets/prism/prism.min.js'
], function() {
Prism.highlightAll();
});
}
/**
* Fetch additional file to initialize iconpicker
*/
if ($('[role=iconpicker]').length && (! individual.length || individual.includes('iconpicker')) && ! ignore_self) {
require.css([
config.base_url + 'assets/bootstrap-iconpicker/css/bootstrap-iconpicker.min.css'
]);
require.js([
config.base_url + 'assets/bootstrap-iconpicker/js/iconset/materialdesignicons.3.3.92.min.js',
config.base_url + 'assets/bootstrap-iconpicker/js/bootstrap-iconpicker.min.js'
], function() {
$('[role=iconpicker]').iconpicker({
searchText: phrase('Search')
});
});
}
/**
* Fetch additional file if to initialize sortable
*/
if ($('[role=sortable-menu]').length && (! individual.length || individual.includes('sortable-menu')) && ! ignore_self) {
$('[role=sortable-menu]').each(function() {
let context = $(this),
maxDepth = 10;
require.css([
config.base_url + 'assets/sortable/sortable.min.css'
]);
require.js([
config.base_url + 'assets/sortable/sortable.min.js'
], function() {
context.sortable({
maxDepth: maxDepth,
selector: "ul",
list: "li",
onChange: function(e) {
context.next('.serialized_data').val(JSON.stringify(context.sortableToHierarchy()));
}
})
.on('click', '.item-add', function(e) {
if ($(this).parents('ul').length >= maxDepth) return;
let new_item = context.find('li.item-placeholder').prop('outerHTML');
new_item = new_item.replace('{{id}}', $(this).parents('ul').children('li').length);
new_item = new_item.replace(' item-placeholder hidden"', '');
new_item = new_item.replace('aria-label="', 'title="');
if ($(this).hasClass('children')) {
if ($(this).closest('li').find('ul:first').length) {
$(new_item).appendTo($(this).closest('li').find('ul:first'));
} else {
$('<ul>' + new_item + '</ul>').appendTo($(this).closest('li'));
}
} else {
$(new_item).appendTo(context);
}
$('[role=iconpicker]').iconpicker({
searchText: phrase('Search')
});
$('[data-bs-toggle=tooltip]').tooltip();
context.trigger('change');
})
.on('click', '.item-remove', function(e) {
e.preventDefault();
$(this).closest('li').slideToggle(200, function() {
$(this).remove();
context.trigger('change');
});
})
.on('change', '.menu-icon', function() {
let _icon = $(this).find('i').attr('class');
$(this).closest('li').attr('data-icon', _icon).parents(context).trigger('change');
})
.on('change keyup', '.menu-label', function(e) {
$(this).closest('li').attr('data-label', $(this).val()).parents(context).trigger('change');
})
.on('change keyup', '.menu-slug', function() {
$(this).closest('li').attr('data-slug', $(this).val()).parents(context).trigger('change');
})
.on('click touch', '.menu-newtab', function() {
$(this).closest('li').attr('data-newtab', ($(this).is(':checked') ? 1 : 0)).parents(context).trigger('change');
})
.on('change', function(e) {
context.next('.serialized_data').val(JSON.stringify(context.sortableToHierarchy()));
});
});
});
}
/**
* Sortable
*/
if ($('[role=sortable]').length && (! individual.length || individual.includes('sortable')) && ! ignore_self) {
$('[role="sortable"]').each(function() {
let context = $(this);
require.css([
config.base_url + 'assets/sortable/sortable.min.css'
]);
require.js([
config.base_url + 'assets/sortable/sortable.min.js'
], function() {
context.sortable({
maxDepth: 0,
selector: (context.attr('data-selector') ? context.attr('data-selector') : 'ul'),
list: (context.attr('data-list') ? context.attr('data-list') : 'li'),
onChange: function(e) {
return;
}
});
});
});
}
/**
* Widgets
*/
if ($('[role=widget]').length && (! individual.length || individual.includes('widget')) && ! ignore_self) {
$('[role="widget"]').each(function() {
$.ajax({
url: $(this).attr('data-source'),
context: this
})
.done(function(response) {
if (typeof response.content !== 'undefined') {
$(this).html(response.content);
const _this = $(this);
setTimeout(function() {
_this.find('.--fetch-comments').trigger('click')
}, 100)
}
reactivate([], true);
});
});
}
}
/**
* Apply on resize context
*/
function _viewport_modifier() {
/**
* Check again the browser viewport
*/
fullHeight = window.innerHeight - (($('[role=header]').outerHeight(true) ?? 0) + ($('[role=breadcrumb]').outerHeight(true) ?? 0));
if (UA != 'mobile') {
$('.full-height').css({
minHeight: fullHeight - (($('[role=meta]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0))
});
require.css([
config.base_url + 'assets/mcustomscrollbar/jquery.mCustomScrollbar.min.css',
config.base_url + 'assets/local/css/mcustomscrollbar.min.css'
]);
require.js([
config.base_url + 'assets/mcustomscrollbar/jquery.mousewheel.min.js',
config.base_url + 'assets/mcustomscrollbar/jquery.mCustomScrollbar.min.js'
], function() {
$('[role=sidebar]').height(fullHeight);
$('[role=table]').width($(window).outerWidth(true) - ($('[role=sidebar]').outerWidth(true) + 24));
$('[role=table]').height(fullHeight - (($('[role=meta]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0)));
$('[role=grid]').height(fullHeight - (($('[role=meta]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0)));
// Scrollable sidebar
$('[role=sidebar]').mCustomScrollbar({
autoHideScrollbar: true,
axis: 'y',
scrollInertia: 200,
setHeight: fullHeight,
advanced: {
updateOnContentResize: true
}
});
// Scrollable table (index of CRUD)
$('[role=table]').mCustomScrollbar({
autoHideScrollbar: true,
axis: 'yx',
scrollInertia: 200,
setWidth: $(window).outerWidth(true) - ($('[role=sidebar]').outerWidth(true) + 24),
setHeight: fullHeight - (($('[role=meta]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0)),
advanced: {
updateOnContentResize: true
}
});
// Scrollable grid (index of CRUD)
$('[role=grid]').mCustomScrollbar({
autoHideScrollbar: true,
axis: 'yx',
scrollInertia: 200,
setHeight: fullHeight - (($('[role=meta]').outerHeight(true) ?? 0) + ($('[role=toolbar]').outerHeight(true) ?? 0) + ($('[role=pagination]').outerHeight(true) ?? 0)),
advanced: {
updateOnContentResize: true
}
});
$('.pretty-scrollbar').mCustomScrollbar({
autoHideScrollbar: true,
axis: 'y',
scrollInertia: 170,
mouseWheelPixels: 170,
setHeight: $(window).outerHeight(true) - (($('[role=header]').outerHeight(true) ?? 0) + ($('[role=breadcrumb]').outerHeight(true) ?? 0) + ($('[role=meta]').outerHeight(true) ?? 0)),
advanced: {
updateOnContentResize: true
},
autoHideScrollbar: false
})
});
}
}
|