drop-downs
drop-down.js
Best way so far
// drop-downs.js export function initDropDowns() { hideAllCodeCmds() if(!document.listenersAdded){ document.addEventListener("click", handleToggle); document.addEventListener("keydown", handleToggle); document.listenersAdded = true } // const dropChilds = document.querySelectorAll('.code-cmd') ? document.querySelectorAll('.code-cmd') : document.querySelectorAll('.topic-snips') function handleToggle(e) { let target; if (e.type === "keydown") { if ((e.key === "Enter" || e.key === " ") && (document.activeElement.classList.contains("drop-down") || document.activeElement.classList.contains("drop-code-cmd"))) { e.preventDefault(); target = document.activeElement; } else { return; // ignore other keys } } else if (e.type === "click") { // Ignore clicks triggered by keyboard if (e.detail === 0) return; target = e.target.closest(".drop-down") || e.target.closest(".drop-code-cmd"); if (!target) return; } // Unified toggle logic const topic = target.closest(".topic"); const snip = target.closest(".snip"); // console.log("Toggled dropdown:", topic); // if (!topic || !snip) return; console.log(snip) if (snip){ toggleCodeSnips(snip) return } if(topic){ toggleTopicSnips(topic) return } } } function toggleCodeSnips(snip) { const codeCmd = snip.querySelector('.code-cmd') codeCmd.classList.toggle('hide') } function hideAllCodeCmds() { const codeCmds = document.querySelectorAll('.code-cmd') codeCmds.forEach(el => { if(!el.classList.contains('show')){ el.classList.add('hide') } }) } function toggleTopicSnips(topic) { const topicSnips = topic.querySelector('.topic-snips') topicSnips.classList.toggle("hide"); // example toggle }
Keyboard Navigation
Letter Focus Code
filter()
and findIndex()
**make a dropCode like dropTopic so each code example can collapse... great job keep going,
you're doing great with implementing the new letterFocus incrementation !!😎
Chat Question: does filter()
work the same as findIndex()
?
ChatGPT said:
Awesome question filter is similar to findIndex, but with one big difference in what it returns.
✅ Both:
- * Take a callback function that checks a condition.
- * Go through the array element by element.
- * Use the callback to test each item.
🔍 Difference: Method Returns findIndex The index of the first matching item filter A new array of all matching items
const as = document.querySelectorAll('a') let asTxtArr = [...as] let lastPressedLetter = ""; let iLetter = 0; function updateAsTxtArr(){ asTxtArr = Array.from(document.querySelectorAll('a')) } addEventListener('keydown', e => { let letter = e.key.toLowerCase() let letteredAs = asTxtArr.filter((el) => el.innerText.toLowerCase().startsWith(letter)) let activeEl = document.activeElement // current focused element let activeIndex = [...asTxtArr].indexOf(activeEl) if(letter != lastPressedLetter){ let closestIndex = letteredAs.findIndex((el) => asTxtArr.indexOf(el) > activeIndex) iLetter = closestIndex !== -1 ? closestIndex : 0 } else { iLetter = (letteredAs.indexOf(activeEl) + 1) % letteredAs.length } if(e.shiftKey){ iLetter = (letteredAs.indexOf(activeEl) - 1 + letteredAs.length) % letteredAs.length } if(letteredAs[iLetter]){ letteredAs[iLetter].focus() } lastPressedLetter = letter })
CamelCase
function toCamelCase(str) { return str .toLowerCase() .replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase()); }
Drop
2
// This page has really good letter focus cycle if(letter == 'c' && !e.metaKey){ if(!e.shiftKey){ copyCodes[iCopyCodes].focus() iCopyCodes = (iCopyCodes + 1) % copyCodes.length } else{ iCopyCodes = (iCopyCodes - 1 + copyCodes.length) % copyCodes.length } copyCodes[iCopyCodes].focus() console.log(iLetter) }
CamelCase function
function toCamelCase(str) { return str .toLowerCase() .replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase()); }
Drop downs
Incrementing / Decrements Letter Focus
function hideTopics(){ }
CamelCase function
function toCamelCase(str) { return str .toLowerCase() .replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase()); }