// const originalAddEventListener = EventTarget.prototype.addEventListener;
|
//
|
// // Override addEventListener to wrap handlers with logging
|
// EventTarget.prototype.addEventListener = function(type, handler, options) {
|
// if (!['mousemove', 'load','mousedown', 'DOMContentLoaded'].includes(type)) { // Only log 'change' events, or remove this condition for all events
|
// const wrappedHandler = function(event) {
|
// console.log(`🎯 ${type} event triggered on:`, event.target);
|
// console.log(`📋 Handler function:`, handler);
|
// console.log(`📊 Event details:`, event);
|
// console.trace('Call stack:'); // Shows where the event was triggered from
|
//
|
// // Call the original handler
|
// return handler.apply(this, arguments);
|
// };
|
//
|
// // Call the original addEventListener with our wrapped handler
|
// return originalAddEventListener.call(this, type, wrappedHandler, options);
|
// } else {
|
// // For non-change events, use original behavior
|
// return originalAddEventListener.call(this, type, handler, options);
|
// }
|
// };
|
|
// A11yHelper - Centralized accessibility functionality
|
class A11yHelper {
|
constructor() {
|
this.liveRegion = document.querySelector('.screen-reader-text.live-region');
|
if(!this.liveRegion){
|
console.log('No accessibility region.');
|
}
|
}
|
|
announce(message, priority = 'polite') {
|
if (!this.liveRegion) return;
|
|
// Set priority - use 'assertive' for critical updates
|
this.liveRegion.setAttribute('aria-live', priority);
|
|
// Clear and set with small delay to ensure announcement
|
this.liveRegion.textContent = '';
|
setTimeout(() => {
|
this.liveRegion.textContent = message;
|
}, 50);
|
}
|
|
announceItems(count, isAppending = false, hasMore = true) {
|
const action = isAppending ? 'Added' : 'Loaded';
|
const more = hasMore ? '. More available to load.' : '. No more available to load.';
|
this.announce(`${action} ${count} new items${more}`);
|
}
|
|
announceEmpty(isFavourites = false) {
|
const message = isFavourites
|
? "No favourites found. Try adding some items to your collection."
|
: "No items found matching your current filters.";
|
this.announce(message);
|
}
|
|
announceNavigation(current, total, isFirst = false, isLast = false) {
|
if (isFirst) {
|
this.announce('At first image');
|
} else if (isLast) {
|
this.announce('At last image');
|
} else {
|
this.announce(`Image ${current} of ${total}`);
|
}
|
}
|
|
trapFocus(element, returnFocus = null) {
|
if (!element) return () => {};
|
|
const focusableElements = element.querySelectorAll(
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
);
|
|
if (!focusableElements.length) return () => {};
|
|
const firstElement = focusableElements[0];
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
// Store previously focused element
|
const previousFocus = returnFocus || document.activeElement;
|
|
// Focus first element
|
firstElement.focus();
|
|
// Handle keyboard navigation
|
const handler = (e) => {
|
if (e.key !== 'Tab') return;
|
|
if (e.shiftKey && document.activeElement === firstElement) {
|
lastElement.focus();
|
e.preventDefault();
|
} else if (!e.shiftKey && document.activeElement === lastElement) {
|
firstElement.focus();
|
e.preventDefault();
|
}
|
};
|
|
element.addEventListener('keydown', handler);
|
|
// Return cleanup function
|
return () => {
|
element.removeEventListener('keydown', handler);
|
if (previousFocus && typeof previousFocus.focus === 'function') {
|
previousFocus.focus();
|
}
|
};
|
}
|
|
makeNavigable(elements, activationCallback) {
|
if (!elements || !elements.length) return;
|
|
Array.from(elements).forEach(element => {
|
if (element.getAttribute('data-keyboard-nav')) return;
|
|
element.setAttribute('data-keyboard-nav', 'true');
|
element.setAttribute('tabindex', '0');
|
|
element.addEventListener('keydown', e => {
|
if (e.key === 'Enter' || e.key === ' ') {
|
e.preventDefault();
|
if (activationCallback) {
|
activationCallback(element);
|
} else {
|
const link = element.querySelector('a');
|
if (link) link.click();
|
}
|
}
|
});
|
});
|
}
|
}
|
|
document.addEventListener('DOMContentLoaded', function() {
|
window.jvbA11y = new A11yHelper();
|
});
|