1/** 2 * Copyright (c) 2024, The Linux Foundation. 3 * SPDX-License-Identifier: Apache-2.0 4 */ 5 6function filterSamples(input) { 7 const searchQuery = input.value.toLowerCase(); 8 const container = input.closest(".code-sample-listing"); 9 10 function removeHighlights(element) { 11 const marks = element.querySelectorAll("mark"); 12 marks.forEach((mark) => { 13 const parent = mark.parentNode; 14 while (mark.firstChild) { 15 parent.insertBefore(mark.firstChild, mark); 16 } 17 parent.removeChild(mark); 18 parent.normalize(); // Merge adjacent text nodes 19 }); 20 } 21 22 function highlightMatches(node, query) { 23 if (node.nodeType === Node.TEXT_NODE) { 24 const text = node.textContent; 25 const index = text.toLowerCase().indexOf(query); 26 if (index !== -1 && query.length > 0) { 27 const highlightedFragment = document.createDocumentFragment(); 28 29 const before = document.createTextNode(text.substring(0, index)); 30 const highlight = document.createElement("mark"); 31 highlight.textContent = text.substring(index, index + query.length); 32 const after = document.createTextNode(text.substring(index + query.length)); 33 34 highlightedFragment.appendChild(before); 35 highlightedFragment.appendChild(highlight); 36 highlightedFragment.appendChild(after); 37 38 node.parentNode.replaceChild(highlightedFragment, node); 39 } 40 } else if (node.nodeType === Node.ELEMENT_NODE) { 41 node.childNodes.forEach((child) => highlightMatches(child, query)); 42 } 43 } 44 45 function processSection(section) { 46 let sectionVisible = false; 47 const lists = section.querySelectorAll(":scope > ul.code-sample-list"); 48 const childSections = section.querySelectorAll(":scope > section"); 49 50 // Process lists directly under this section 51 lists.forEach((list) => { 52 let listVisible = false; 53 const items = list.querySelectorAll("li"); 54 55 items.forEach((item) => { 56 const nameElement = item.querySelector(".code-sample-name"); 57 const descElement = item.querySelector(".code-sample-description"); 58 59 removeHighlights(nameElement); 60 removeHighlights(descElement); 61 62 const sampleName = nameElement.textContent.toLowerCase(); 63 const sampleDescription = descElement.textContent.toLowerCase(); 64 65 if ( 66 sampleName.includes(searchQuery) || 67 sampleDescription.includes(searchQuery) 68 ) { 69 if (searchQuery) { 70 highlightMatches(nameElement, searchQuery); 71 highlightMatches(descElement, searchQuery); 72 } 73 74 item.style.display = ""; 75 listVisible = true; 76 sectionVisible = true; 77 } else { 78 item.style.display = "none"; 79 } 80 }); 81 82 // Show or hide the list based on whether any items are visible 83 list.style.display = listVisible ? "" : "none"; 84 }); 85 86 // Recursively process child sections 87 childSections.forEach((childSection) => { 88 const childVisible = processSection(childSection); 89 if (childVisible) { 90 sectionVisible = true; 91 } 92 }); 93 94 // Show or hide the section heading based on visibility 95 const heading = section.querySelector( 96 ":scope > h2, :scope > h3, :scope > h4, :scope > h5, :scope > h6" 97 ); 98 if (sectionVisible) { 99 if (heading) heading.style.display = ""; 100 section.style.display = ""; 101 } else { 102 if (heading) heading.style.display = "none"; 103 section.style.display = "none"; 104 } 105 106 return sectionVisible; 107 } 108 109 // Start processing from the container 110 processSection(container); 111 112 // Ensure the input and its container are always visible 113 input.style.display = ""; 114 container.style.display = ""; 115} 116