MCPcopy
hub / github.com/codedogQBY/ReadAny / createTOCView

Function createTOCView

packages/foliate-js/ui/tree.js:59–168  ·  view source on GitHub ↗
(toc, onclick)

Source from the content-addressed store, hash-verified

57
58// https://www.w3.org/TR/wai-aria-practices-1.2/examples/treeview/treeview-navigation.html
59export const createTOCView = (toc, onclick) => {
60 const $toc = document.createElement("ol");
61 $toc.setAttribute("role", "tree");
62 const list = [];
63 const map = new Map();
64 const createItem = createTOCItemElement(list, map, onclick);
65 $toc.replaceChildren(...toc.map((item) => createItem(item)));
66
67 const isTreeItem = (item) => item?.getAttribute("role") === "treeitem";
68 const getParents = function* (el) {
69 for (let parent = el.parentNode; parent !== $toc; parent = parent.parentNode) {
70 const item = parent.previousElementSibling;
71 if (isTreeItem(item)) yield item;
72 }
73 };
74
75 let currentItem, currentVisibleParent;
76 $toc.addEventListener("focusout", () => {
77 if (!currentItem) return;
78 // reset parent focus from last time
79 if (currentVisibleParent) currentVisibleParent.tabIndex = -1;
80 // if current item is visible, let it have the focus
81 if (currentItem.offsetParent) {
82 currentItem.tabIndex = 0;
83 return;
84 }
85 // current item is hidden; give focus to the nearest visible parent
86 for (const item of getParents(currentItem)) {
87 if (item.offsetParent) {
88 item.tabIndex = 0;
89 currentVisibleParent = item;
90 break;
91 }
92 }
93 });
94
95 const setCurrentHref = (href) => {
96 if (currentItem) {
97 currentItem.removeAttribute("aria-current");
98 currentItem.tabIndex = -1;
99 }
100 const el = map.get(href);
101 if (!el) {
102 currentItem = list[0];
103 currentItem.tabIndex = 0;
104 return;
105 }
106 for (const item of getParents(el)) item.setAttribute("aria-expanded", "true");
107 el.setAttribute("aria-current", "page");
108 el.tabIndex = 0;
109 el.scrollIntoView({ behavior: "smooth", block: "center" });
110 currentItem = el;
111 };
112
113 const acceptNode = (node) =>
114 isTreeItem(node) && node.offsetParent ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
115 const iter = document.createTreeWalker($toc, 1, { acceptNode });
116 const getIter = (current) => ((iter.currentNode = current), iter);

Callers 1

openMethod · 0.90

Calls 7

createTOCItemElementFunction · 0.85
createItemFunction · 0.85
isTreeItemFunction · 0.85
getIterFunction · 0.85
setAttributeMethod · 0.80
mapMethod · 0.80
nextMethod · 0.65

Tested by

no test coverage detected