refactor: Improve toast notification rendering and event handling

- Refactored the ShowToastJS function to create toast elements using DOM methods for better safety and maintainability.
- Changed the event listener for the 'showToast' event from document.body to document for improved event handling.
- Ensured that the message content is set using textContent to prevent potential XSS vulnerabilities.
This commit is contained in:
StarFleetCPTN
2025-04-07 11:21:11 -07:00
parent 0f46b20fc4
commit 16e7b7e6e5
2 changed files with 31 additions and 18 deletions
+25 -12
View File
@@ -33,22 +33,36 @@ templ ShowToastJS() {
textColorClass = 'text-blue-500 dark:text-blue-200'; textColorClass = 'text-blue-500 dark:text-blue-200';
} }
// Set inner HTML with appropriate icon and message // Create icon div
toast.innerHTML = ` const iconDiv = document.createElement('div');
<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg ${iconClass}"> iconDiv.className = `inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg ${iconClass}`;
${type === 'success' iconDiv.innerHTML = type === 'success'
? '<i class="fas fa-check"></i>' ? '<i class="fas fa-check"></i>'
: type === 'error' : type === 'error'
? '<i class="fas fa-exclamation-circle"></i>' ? '<i class="fas fa-exclamation-circle"></i>'
: '<i class="fas fa-info-circle"></i>'} : '<i class="fas fa-info-circle"></i>';
</div>
<div class="ml-3 text-sm font-normal">${message}</div> // Create message div and set text content safely
<button type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#${toast.id}" aria-label="Close"> const messageDiv = document.createElement('div');
messageDiv.className = 'ml-3 text-sm font-normal';
messageDiv.textContent = message; // Use textContent for safety
// Create close button
const closeButton = document.createElement('button'); // Keep this declaration
closeButton.type = 'button';
closeButton.className = 'ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700';
closeButton.setAttribute('data-dismiss-target', `#${toast.id}`);
closeButton.setAttribute('aria-label', 'Close');
closeButton.innerHTML = `
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<i class="fas fa-times"></i> <i class="fas fa-times"></i>
</button>
`; `;
// Append elements to the toast
toast.appendChild(iconDiv);
toast.appendChild(messageDiv);
toast.appendChild(closeButton);
// Add toast to container // Add toast to container
toastContainer.appendChild(toast); toastContainer.appendChild(toast);
@@ -58,9 +72,8 @@ templ ShowToastJS() {
toast.classList.add('translate-y-0', 'opacity-100'); toast.classList.add('translate-y-0', 'opacity-100');
}, 10); }, 10);
// Add event listener to close button // Add event listener to the close button we created earlier
const closeButton = toast.querySelector('button[data-dismiss-target]'); closeButton.addEventListener('click', function() { // Use the existing closeButton variable
closeButton.addEventListener('click', function() {
// Animate out before removing // Animate out before removing
toast.classList.add('opacity-0', 'translate-y-4'); toast.classList.add('opacity-0', 'translate-y-4');
setTimeout(() => { setTimeout(() => {
+1 -1
View File
@@ -449,7 +449,7 @@ function enhanceMobileForms() {
// Listen for custom 'showToast' event triggered by HX-Trigger // Listen for custom 'showToast' event triggered by HX-Trigger
document.body.addEventListener('showToast', function(event) { document.addEventListener('showToast', function(event) { // Changed from document.body
// Debug logs removed // Debug logs removed
if (event.detail && event.detail.message && event.detail.type) { if (event.detail && event.detail.message && event.detail.type) {
// Call the globally defined showToast function from toast_js.templ // Call the globally defined showToast function from toast_js.templ