File size: 3,990 Bytes
fa3378e fcfd940 fa3378e fcfd940 fa3378e fcfd940 fa3378e fcfd940 fa3378e fcfd940 fa3378e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | // Shared JavaScript functions
document.addEventListener('DOMContentLoaded', function() {
// Set language attribute
document.documentElement.lang = 'en';
// Skip to content link
const skipLink = document.createElement('a');
skipLink.href = '#main-content';
skipLink.className = 'skip-link sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:bg-white focus:p-4 focus:z-50';
skipLink.textContent = 'Skip to main content';
document.body.insertBefore(skipLink, document.body.firstChild);
// Add accessible names to interactive elements
document.querySelectorAll('[data-feather]').forEach(icon => {
const parent = icon.parentElement;
if (parent.tagName === 'A' || parent.tagName === 'BUTTON') {
const label = parent.textContent.trim() || icon.getAttribute('aria-label') || parent.getAttribute('title');
if (label) {
parent.setAttribute('aria-label', label);
}
if (parent.tagName === 'BUTTON' && !parent.getAttribute('type')) {
parent.setAttribute('type', 'button');
}
}
});
// Ensure all images have alt text
document.querySelectorAll('img:not([alt])').forEach(img => {
img.setAttribute('alt', '');
});
// Add landmark roles
const main = document.querySelector('main');
if (main && !main.getAttribute('role')) {
main.setAttribute('role', 'main');
}
// Manage focus for modals
document.addEventListener('keydown', function(e) {
if (e.key === 'Tab' && document.querySelector('.modal[aria-modal="true"]')) {
handleModalFocus(e);
}
});
// Initialize tooltips
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Form validation example
const 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);
});
// Password visibility toggle
const passwordToggles = document.querySelectorAll('.password-toggle');
passwordToggles.forEach(toggle => {
toggle.addEventListener('click', function() {
const input = this.previousElementSibling;
const icon = this.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.setAttribute('data-feather', 'eye-off');
} else {
input.type = 'password';
icon.setAttribute('data-feather', 'eye');
}
feather.replace();
});
});
});
// API call example for account balance
async function fetchAccountBalance() {
try {
// In a real app, this would be a secure API call with authentication
const response = await fetch('https://api.example.com/balance', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN'
}
});
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching account balance:', error);
return null;
}
}
// Format currency
function formatCurrency(amount) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
// Format date
function formatDate(dateString) {
const options = { year: 'numeric', month: 'short', day: 'numeric' };
return new Date(dateString).toLocaleDateString('en-US', options);
} |