mirror of
https://github.com/itflow-org/itflow
synced 2026-09-20 05:31:15 +00:00
Migrate fully away from Jquery Stage 1
This commit is contained in:
143
js/ajax_modal.js
143
js/ajax_modal.js
@@ -1,61 +1,90 @@
|
||||
// Ajax Modal Load Script
|
||||
$(document).on('click', '.ajax-modal', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const $trigger = $(this);
|
||||
|
||||
// Prefer data-modal-url, fallback to href
|
||||
let modalUrl = $trigger.data('modal-url') || $trigger.attr('href') || '#';
|
||||
const modalSize = $trigger.data('modal-size') || 'md';
|
||||
const modalId = 'ajaxModal_' + Date.now();
|
||||
|
||||
// If no usable URL, bail
|
||||
if (!modalUrl || modalUrl === '#') {
|
||||
console.warn('ajax-modal: No modal URL found on trigger:', this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading spinner while fetching content
|
||||
const loadingSpinner = `
|
||||
<div id="modal-loading-spinner" class="text-center p-5">
|
||||
<i class="fas fa-spinner fa-spin fa-2x text-muted"></i>
|
||||
</div>`;
|
||||
$('.app-main').append(loadingSpinner);
|
||||
|
||||
// Make AJAX request
|
||||
$.ajax({
|
||||
url: modalUrl,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
$('#modal-loading-spinner').remove();
|
||||
|
||||
if (response.error) {
|
||||
alert(response.error);
|
||||
document.addEventListener('click', function (e) {
|
||||
const trigger = e.target.closest('.ajax-modal');
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modalHtml = `
|
||||
<div class="modal fade" id="${modalId}" tabindex="-1">
|
||||
<div class="modal-dialog modal-${modalSize}">
|
||||
<div class="modal-content border-dark">
|
||||
${response.content}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
$('.app-main').append(modalHtml);
|
||||
const $modal = $('#' + modalId);
|
||||
bootstrap.Modal.getOrCreateInstance($modal[0]).show();
|
||||
|
||||
$modal.on('hidden.bs.modal', function () {
|
||||
$(this).remove();
|
||||
});
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
$('#modal-loading-spinner').remove();
|
||||
alert('Error loading modal content. Please try again.');
|
||||
console.error('Modal AJAX Error:', status, error);
|
||||
}
|
||||
});
|
||||
e.preventDefault();
|
||||
|
||||
// Prefer data-modal-url, fallback to href
|
||||
const modalUrl = trigger.dataset.modalUrl || trigger.getAttribute('href') || '#';
|
||||
const modalSize = trigger.dataset.modalSize || 'md';
|
||||
const modalId = 'ajaxModal_' + Date.now();
|
||||
|
||||
// If no usable URL, bail
|
||||
if (!modalUrl || modalUrl === '#') {
|
||||
console.warn('ajax-modal: No modal URL found on trigger:', trigger);
|
||||
return;
|
||||
}
|
||||
|
||||
const host = document.querySelector('.app-main') || document.body;
|
||||
|
||||
// Show loading spinner while fetching content
|
||||
const spinner = document.createElement('div');
|
||||
spinner.id = 'modal-loading-spinner';
|
||||
spinner.className = 'text-center p-5';
|
||||
spinner.innerHTML = '<i class="fas fa-spinner fa-spin fa-2x text-muted"></i>';
|
||||
host.appendChild(spinner);
|
||||
|
||||
function clearSpinner() {
|
||||
const el = document.getElementById('modal-loading-spinner');
|
||||
if (el) {
|
||||
el.remove();
|
||||
}
|
||||
}
|
||||
|
||||
fetch(modalUrl, {
|
||||
method: 'GET',
|
||||
headers: { 'Accept': 'application/json' },
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function (res) {
|
||||
if (!res.ok) {
|
||||
throw new Error('HTTP ' + res.status);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(function (response) {
|
||||
clearSpinner();
|
||||
|
||||
if (response.error) {
|
||||
alert(response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'modal fade';
|
||||
wrapper.id = modalId;
|
||||
wrapper.tabIndex = -1;
|
||||
wrapper.innerHTML =
|
||||
'<div class="modal-dialog modal-' + modalSize + '">' +
|
||||
'<div class="modal-content border-dark">' +
|
||||
response.content +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
host.appendChild(wrapper);
|
||||
|
||||
// innerHTML does not execute <script> tags. The modal payload ends
|
||||
// with modal_footer.php, which re-runs app.js to wire up Tom Select,
|
||||
// IMask, flatpickr and friends - so re-inject them by hand.
|
||||
wrapper.querySelectorAll('script').forEach(function (old) {
|
||||
const s = document.createElement('script');
|
||||
for (const attr of old.attributes) {
|
||||
s.setAttribute(attr.name, attr.value);
|
||||
}
|
||||
s.textContent = old.textContent;
|
||||
old.replaceWith(s);
|
||||
});
|
||||
|
||||
bootstrap.Modal.getOrCreateInstance(wrapper).show();
|
||||
|
||||
wrapper.addEventListener('hidden.bs.modal', function () {
|
||||
wrapper.remove();
|
||||
});
|
||||
})
|
||||
.catch(function (error) {
|
||||
clearSpinner();
|
||||
alert('Error loading modal content. Please try again.');
|
||||
console.error('Modal AJAX Error:', error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
// Delegated on document rather than bound to the links present at page load, so
|
||||
// that confirm-link also works on markup injected by an ajax modal
|
||||
$(document).ready(function() {
|
||||
$(document).off('click.itflowConfirm').on('click.itflowConfirm', 'a.confirm-link', function(e) {
|
||||
e.preventDefault();
|
||||
document.addEventListener('click', function (e) {
|
||||
const link = e.target.closest('a.confirm-link');
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
// Save the link reference to use after confirmation
|
||||
var linkReference = this;
|
||||
const modalEl = document.getElementById('confirmationModal');
|
||||
const confirmBtn = document.getElementById('confirmSubmitBtn');
|
||||
if (!modalEl || !confirmBtn) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the confirmation modal
|
||||
bootstrap.Modal.getOrCreateInstance(document.getElementById('confirmationModal')).show();
|
||||
// Replacing the node drops any handler left over from a previous link,
|
||||
// which is what .off('click') used to do here.
|
||||
const freshBtn = confirmBtn.cloneNode(true);
|
||||
confirmBtn.replaceWith(freshBtn);
|
||||
freshBtn.addEventListener('click', function () {
|
||||
window.location.href = link.getAttribute('href');
|
||||
});
|
||||
|
||||
// When the submission is confirmed via the modal
|
||||
$("#confirmSubmitBtn").off('click').on('click', function() {
|
||||
window.location.href = $(linkReference).attr('href');
|
||||
});
|
||||
});
|
||||
});
|
||||
bootstrap.Modal.getOrCreateInstance(modalEl).show();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
$(document).ready(function(){
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Add class to tables
|
||||
$('div.prettyContent table').addClass('table');
|
||||
document.querySelectorAll('div.prettyContent table').forEach(function (el) {
|
||||
el.classList.add('table');
|
||||
});
|
||||
|
||||
// Add img-fluid class to img tags
|
||||
$('div.prettyContent img').addClass('img-fluid');
|
||||
});
|
||||
document.querySelectorAll('div.prettyContent img').forEach(function (el) {
|
||||
el.classList.add('img-fluid');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
$(document).ready(function () {
|
||||
$('.modal').each(function () {
|
||||
const modalId = `#${$(this).attr('id')}`;
|
||||
if (window.location.href.indexOf(modalId) !== -1) {
|
||||
bootstrap.Modal.getOrCreateInstance($(modalId)[0]).show();
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('.modal').forEach(function (modal) {
|
||||
if (modal.id && window.location.href.indexOf('#' + modal.id) !== -1) {
|
||||
bootstrap.Modal.getOrCreateInstance(modal).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user