155 lines
5.6 KiB
JavaScript
155 lines
5.6 KiB
JavaScript
// Custom JavaScript for Delphi Database
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// Initialize tooltips if any
|
||
if (window.bootstrap && bootstrap.Tooltip) {
|
||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||
tooltipTriggerList.forEach(function (tooltipTriggerEl) {
|
||
new bootstrap.Tooltip(tooltipTriggerEl);
|
||
});
|
||
}
|
||
|
||
// Auto-hide alerts after 5 seconds
|
||
var alerts = document.querySelectorAll('.alert:not(.alert-permanent)');
|
||
alerts.forEach(function(alert) {
|
||
setTimeout(function() {
|
||
var bsAlert = new bootstrap.Alert(alert);
|
||
bsAlert.close();
|
||
}, 5000);
|
||
});
|
||
|
||
// Confirm delete actions
|
||
var deleteButtons = document.querySelectorAll('[data-confirm-delete]');
|
||
deleteButtons.forEach(function(button) {
|
||
button.addEventListener('click', function(e) {
|
||
var message = this.getAttribute('data-confirm-delete') || 'Are you sure you want to delete this item?';
|
||
if (!confirm(message)) {
|
||
e.preventDefault();
|
||
}
|
||
});
|
||
});
|
||
|
||
// Form validation enhancement
|
||
var forms = document.querySelectorAll('.needs-validation');
|
||
Array.prototype.slice.call(forms).forEach(function(form) {
|
||
form.addEventListener('submit', function(event) {
|
||
if (!form.checkValidity()) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
}
|
||
form.classList.add('was-validated');
|
||
}, false);
|
||
});
|
||
|
||
// Dynamic form field enabling/disabling
|
||
var toggleFields = document.querySelectorAll('[data-toggle-field]');
|
||
toggleFields.forEach(function(element) {
|
||
element.addEventListener('change', function() {
|
||
var targetSelector = this.getAttribute('data-toggle-field');
|
||
var targetField = document.querySelector(targetSelector);
|
||
if (targetField) {
|
||
targetField.disabled = !this.checked;
|
||
}
|
||
});
|
||
});
|
||
|
||
// Auto-compute Amount = Quantity × Rate in ledger add form
|
||
var qtyInput = document.querySelector('form[action*="/ledger"] .js-qty');
|
||
var rateInput = document.querySelector('form[action*="/ledger"] .js-rate');
|
||
var amountInput = document.querySelector('form[action*="/ledger"] .js-amount');
|
||
|
||
function recomputeAmount() {
|
||
if (!qtyInput || !rateInput || !amountInput) return;
|
||
var q = parseFloat(qtyInput.value);
|
||
var r = parseFloat(rateInput.value);
|
||
if (!isNaN(q) && !isNaN(r)) {
|
||
var amt = (q * r);
|
||
amountInput.value = amt.toFixed(2);
|
||
}
|
||
}
|
||
|
||
if (qtyInput) qtyInput.addEventListener('input', recomputeAmount);
|
||
if (rateInput) rateInput.addEventListener('input', recomputeAmount);
|
||
|
||
// Generic select-all for answer tables
|
||
document.querySelectorAll('.js-answer-table').forEach(function(form) {
|
||
var selectAll = form.querySelector('.js-select-all');
|
||
if (!selectAll) return;
|
||
selectAll.addEventListener('change', function() {
|
||
var checkboxes = form.querySelectorAll('input[type="checkbox"][name]');
|
||
checkboxes.forEach(function(cb) {
|
||
if (cb !== selectAll) cb.checked = selectAll.checked;
|
||
});
|
||
});
|
||
});
|
||
|
||
// Submit selection to alternate endpoints using data-action
|
||
document.querySelectorAll('.js-submit-to').forEach(function(link) {
|
||
link.addEventListener('click', function(e) {
|
||
e.preventDefault();
|
||
var container = link.closest('.table-responsive') || document;
|
||
var form = container.querySelector('form.js-answer-table');
|
||
if (!form) form = document.querySelector('form.js-answer-table');
|
||
if (!form) return;
|
||
var original = form.getAttribute('action');
|
||
var action = link.getAttribute('data-action');
|
||
if (action) form.setAttribute('action', action);
|
||
try {
|
||
form.submit();
|
||
} finally {
|
||
if (original) form.setAttribute('action', original);
|
||
}
|
||
});
|
||
});
|
||
|
||
// Field help: show contextual help from data-help on focus
|
||
function attachFieldHelp(container) {
|
||
if (!container) return;
|
||
var helpEl = container.querySelector('#fieldHelp');
|
||
if (!helpEl) return;
|
||
container.querySelectorAll('input, select, textarea').forEach(function(field) {
|
||
field.addEventListener('focus', function() {
|
||
var text = field.getAttribute('data-help');
|
||
if (text) helpEl.textContent = text;
|
||
});
|
||
field.addEventListener('blur', function() {
|
||
// Optionally keep last help, or reset
|
||
});
|
||
});
|
||
}
|
||
|
||
// Attach help to known forms/sections
|
||
document.querySelectorAll('form').forEach(function(form) {
|
||
attachFieldHelp(form.closest('.card-body') || form);
|
||
});
|
||
});
|
||
|
||
// Utility functions
|
||
function formatDate(dateString) {
|
||
if (!dateString) return '';
|
||
var date = new Date(dateString);
|
||
return date.toLocaleDateString();
|
||
}
|
||
|
||
function formatCurrency(amount) {
|
||
if (!amount) return '$0.00';
|
||
return new Intl.NumberFormat('en-US', {
|
||
style: 'currency',
|
||
currency: 'USD'
|
||
}).format(amount);
|
||
}
|
||
|
||
function showLoading(button) {
|
||
if (button) {
|
||
button.disabled = true;
|
||
button.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Loading...';
|
||
}
|
||
}
|
||
|
||
function hideLoading(button, originalText) {
|
||
if (button) {
|
||
button.disabled = false;
|
||
button.innerHTML = originalText;
|
||
}
|
||
}
|