mirror of
https://github.com/itflow-org/itflow
synced 2026-02-28 19:04:52 +00:00
Added data-bulk to the ajax modal to allow for bulk GET collection of selected ids that have a class of bulk-select, converted expense and client bulk modals to use the the new ajax-modal
This commit is contained in:
126
js/ajax_modal.js
126
js/ajax_modal.js
@@ -1,66 +1,74 @@
|
||||
// Ajax Modal Load Script
|
||||
//
|
||||
/* Example Triggering -->
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-primary ajax-modal" // Triggers the AJAX Modal
|
||||
data-modal-size = "lg" // Optional: Defaults to md
|
||||
data-modal-url="modals/contact/contact_edit.php?id=id">
|
||||
Edit Contact
|
||||
</button>
|
||||
|
||||
*/
|
||||
$(document).on('click', '.ajax-modal', function (e) {
|
||||
e.preventDefault();
|
||||
e.preventDefault();
|
||||
|
||||
const $trigger = $(this);
|
||||
const modalUrl = $trigger.data('modal-url');
|
||||
const modalSize = $trigger.data('modal-size') || 'md';
|
||||
const modalId = 'ajaxModal_' + new Date().getTime();
|
||||
const $trigger = $(this);
|
||||
let modalUrl = $trigger.data('modal-url');
|
||||
const modalSize = $trigger.data('modal-size') || 'md';
|
||||
const modalId = 'ajaxModal_' + new Date().getTime();
|
||||
|
||||
// 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>
|
||||
// -------- Optional bulk mode (activated via data-bulk="true") --------
|
||||
if ($trigger.data('bulk') === true || $trigger.data('bulk') === 'true') {
|
||||
const selector = $trigger.data('bulk-selector') || '.bulk-select:checked';
|
||||
const param = $trigger.data('bulk-param') || 'selected_ids[]';
|
||||
|
||||
const ids = Array.from(document.querySelectorAll(selector)).map(cb => cb.value);
|
||||
|
||||
if (!ids.length) {
|
||||
alert('Please select at least one item.');
|
||||
return; // abort opening modal
|
||||
}
|
||||
|
||||
// Merge ids into existing query string safely
|
||||
const urlObj = new URL(modalUrl, window.location.href);
|
||||
ids.forEach(id => urlObj.searchParams.append(param, id));
|
||||
|
||||
// Preserve path + updated query (avoid absolute origin for relative AJAX)
|
||||
modalUrl = urlObj.pathname + (urlObj.search ? '?' + urlObj.searchParams.toString() : '');
|
||||
}
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 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>`;
|
||||
$('.content-wrapper').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);
|
||||
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>`;
|
||||
$('.content-wrapper').append(loadingSpinner);
|
||||
|
||||
// Make AJAX request
|
||||
$.ajax({
|
||||
url: modalUrl,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
$('#modal-loading-spinner').remove();
|
||||
$('.content-wrapper').append(modalHtml);
|
||||
const $modal = $('#' + modalId);
|
||||
$modal.modal('show');
|
||||
|
||||
if (response.error) {
|
||||
alert(response.error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build modal wrapper
|
||||
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>`;
|
||||
|
||||
$('.content-wrapper').append(modalHtml);
|
||||
const $modal = $('#' + modalId);
|
||||
$modal.modal('show');
|
||||
|
||||
// Remove modal after it's closed
|
||||
$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);
|
||||
}
|
||||
});
|
||||
});
|
||||
$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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,40 +1,54 @@
|
||||
// Allow selecting and editing multiple records at once
|
||||
// bulk_actions.js
|
||||
// Allow selecting and editing multiple records at once (no <form> dependency)
|
||||
|
||||
var form = document.getElementById("bulkActions"); // Get the form element by its id
|
||||
var checkboxes = form.querySelectorAll('input[type="checkbox"].bulk-select'); // Select only checkboxes with class "bulk-select"
|
||||
var selectedCount = document.getElementById("selectedCount");
|
||||
var selectAllCheckbox = document.getElementById("selectAllCheckbox"); // The "select all" checkbox
|
||||
|
||||
// Event listener for each checkbox
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].addEventListener("click", updateSelectedCount);
|
||||
// --- Helpers ---
|
||||
function getCheckboxes() {
|
||||
// Always query fresh in case rows are re-rendered
|
||||
return Array.from(document.querySelectorAll('input[type="checkbox"].bulk-select'));
|
||||
}
|
||||
|
||||
function getSelectedIds() {
|
||||
return getCheckboxes()
|
||||
.filter(cb => cb.checked)
|
||||
.map(cb => cb.value);
|
||||
}
|
||||
|
||||
// Function to update the count of selected checkboxes
|
||||
function updateSelectedCount() {
|
||||
var count = 0;
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked) {
|
||||
count++;
|
||||
const count = getSelectedIds().length;
|
||||
const selectedCountEl = document.getElementById('selectedCount');
|
||||
if (selectedCountEl) {
|
||||
selectedCountEl.textContent = count;
|
||||
}
|
||||
}
|
||||
selectedCount.textContent = count; // Display the count
|
||||
|
||||
// Show or hide the multi-action button
|
||||
document.getElementById("bulkActionButton").hidden = count === 0;
|
||||
const bulkBtn = document.getElementById('bulkActionButton');
|
||||
if (bulkBtn) {
|
||||
bulkBtn.hidden = count === 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check/uncheck all checkboxes
|
||||
// --- Select All Handling ---
|
||||
function checkAll(source) {
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].checked = source.checked;
|
||||
}
|
||||
updateSelectedCount(); // Update the count after changing checkbox states
|
||||
getCheckboxes().forEach(cb => {
|
||||
cb.checked = source.checked;
|
||||
});
|
||||
updateSelectedCount();
|
||||
}
|
||||
|
||||
// Event listener for the "select all" checkbox
|
||||
// Wire select-all checkbox if present
|
||||
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
|
||||
if (selectAllCheckbox) {
|
||||
selectAllCheckbox.addEventListener("click", function() {
|
||||
checkAll(this);
|
||||
});
|
||||
selectAllCheckbox.addEventListener('click', function () {
|
||||
checkAll(this);
|
||||
});
|
||||
}
|
||||
|
||||
// --- Per-row Checkbox Handling ---
|
||||
// Use event delegation so it still works if table rows are re-rendered
|
||||
document.addEventListener('click', function (e) {
|
||||
const cb = e.target.closest('input[type="checkbox"].bulk-select');
|
||||
if (!cb) return;
|
||||
updateSelectedCount();
|
||||
});
|
||||
|
||||
// --- Initialize count on page load ---
|
||||
document.addEventListener('DOMContentLoaded', updateSelectedCount);
|
||||
|
||||
Reference in New Issue
Block a user