File size: 3,206 Bytes
c120a1c |
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 110 111 112 113 114 115 116 117 |
/**
* Shared module between login and main app.
* Be careful what you import!
*/
const buttonSelectors = [
'.menu_button',
'.right_menu_button',
'.mes_button',
'.drawer-icon',
'.inline-drawer-icon',
'.swipe_left',
'.swipe_right',
'.character_select',
'.tags .tag',
'.jg-menu .jg-button',
'.bg_example .mobile-only-menu-toggle',
'.paginationjs-pages li a',
].join(', ');
const listSelectors = [
'.options-content',
'.list-group',
'#rm_print_characters_block',
'#rm_group_members',
'#rm_group_add_members',
'.tag_view_list_tags',
'.secretKeyManagerList',
'.recentChatList',
'.dataMaidCategoryContent',
'#userList',
'.bg_list',
].join(', ');
const listItemSelectors = [
'.options-content .list-group-item',
'.list-group .list-group-item',
'#rm_print_characters_block .entity_block',
'#rm_group_members .group_member',
'#rm_group_add_members .group_member',
'.tag_view_list_tags .tag_view_item',
'.secretKeyManagerList .secretKeyManagerItem',
'.recentChatList .recentChat',
'.dataMaidCategoryContent .dataMaidItem',
'#userList .userSelect',
'.bg_list .bg_example',
].join(', ');
const toolbarSelectors = [
'.jg-menu',
].join(', ');
/** @type {Record<string, (element: Element) => void>} */
const a11yRules = {
[buttonSelectors]: (element) => {
element.setAttribute('role', 'button');
},
[listSelectors]: (element) => {
element.setAttribute('role', 'list');
},
[listItemSelectors]: (element) => {
element.setAttribute('role', 'listitem');
},
[toolbarSelectors]: (element) => {
element.setAttribute('role', 'toolbar');
},
'#toast-container .toast': (element) => {
element.setAttribute('role', 'status');
},
};
/**
* Apply accessibility rules to an element.
* @param {Element} element Element to process.
*/
function applyA11yRules(element) {
try {
for (const [selector, rule] of Object.entries(a11yRules)) {
// Apply if the element directly matches the selector
if (element.matches(selector)) {
rule(element);
}
// Apply the rule to descendants
element.querySelectorAll(selector).forEach(rule);
}
} catch (error) {
console.error('Error applying accessibility rules to element:', element, error);
}
}
function setAccessibilityObserver() {
// Apply for existing elements
applyA11yRules(document.body);
// Setup observer for dynamic content
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
for (const addedNode of mutation.addedNodes) {
if (addedNode instanceof Element && addedNode.nodeType === Node.ELEMENT_NODE) {
applyA11yRules(addedNode);
}
}
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
export function initAccessibility() {
setAccessibilityObserver();
}
|