简体   繁体   中英

How to use search/filter for HTML Divs generated from JSON data using JavaScript?

I'm trying to add a filter for the links/divs generated from JSON data.

I already have a search filter working here without a problem IF the data isn't generated via JSON format. But I really need to use JSON for faster loading and processing.

The problem is, it fails to filter the links when doing so. It's supposed to filter divs based on the text inside <a></a> tags, including some hidden texts inside the <span> ..

In this example, it can filter only the first item in the JSON, but not for the rest.

 // Links Filter var input = document.getElementById("search-filter-cards"); input.addEventListener("input", searchFilterDivsMenu); function searchFilterDivsMenu(e) { var filter = e.target.value.toUpperCase(); var list = document.getElementById("links-list"); var divs = list.getElementsByTagName("div"); for (var i = 0; i < divs.length; i++) { var a = divs[i].getElementsByTagName("a")[0]; if (a) { if (a.innerHTML.toUpperCase().indexOf(filter) > -1) { divs[i].style.display = ""; } else { divs[i].style.display = "none"; } } } } // JSON Data for each links const maincards = { "linksList": [{ 'name': 'Java Bookmarks', 'title': 'Java Bookmarks', 'favicon': '../assets/links-favicons/java-bookmarks.png', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Chrono', 'title': 'Chrono', 'favicon': '../assets/links-favicons/chrono.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Kanban (May)', 'title': 'EDEN Kanban', 'favicon': '../assets/links-favicons/kanban.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out, Kanban board', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, ] }; const createMainCardLinks = ({ name, title, favicon, url, tags, linkattributes }) => ` <div class="card link-container"> <img class="link-img" src="${favicon}"/> <a class="link-title stretched-link" href="${url}" ${linkattributes} title="${title}">${name} <span class="h-0">${tags}</span></a> </div> `; const links = maincards.linksList.map(createMainCardLinks); links.forEach(links => { document.getElementById("load-json-data").innerHTML += links; });
 .h-0 { display: none; }
 <body> <input id="search-filter-cards" type="text" autocomplete="off" placeholder="Type here to search"> <div id="links-list"> <div class="link-headers"><a class="mb-0">Sample Links</a></div> <div id="load-json-data"></div> </div> </body>

I'm a beginner in JS and I couldn't figure out this problem for some time now. Anyways, thanks in advance for any help.

Took me forever to notice your got ALL the divs in the links-list instead of load-json-data

Here is an improved version. It is simplified and because I only toggle the divs in load-json-data it works

 // Links Filter var input = document.getElementById("search-filter-cards"); input.addEventListener("input", searchFilterDivsMenu); function searchFilterDivsMenu(e) { const filter = e.target.value.toUpperCase(); const cards = document.querySelectorAll("#links-list .card"); cards.forEach(card => { var a = card.querySelector("a"); // console.log(filter, "|", a.textContent.toUpperCase(), "|", a.textContent.toUpperCase().indexOf(filter)) card.hidden = !a || (filter && a.textContent.toUpperCase().indexOf(filter) === -1); }) } // JSON Data for each links const maincards = { "linksList": [{ 'name': 'Java Bookmarks', 'title': 'Java Bookmarks', 'favicon': '../assets/links-favicons/java-bookmarks.png', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Chrono', 'title': 'Chrono', 'favicon': '../assets/links-favicons/chrono.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Kanban (May)', 'title': 'EDEN Kanban', 'favicon': '../assets/links-favicons/kanban.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out, Kanban board', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, ] }; const createMainCardLinks = ({ name, title, favicon, url, tags, linkattributes }) => ` <div class="card link-container"> <img class="link-img" src="${favicon}"/> <a class="link-title stretched-link" href="${url}" ${linkattributes} title="${title}">${name} <span class="h-0">${tags}</span></a> </div> `; const links = maincards.linksList.map(createMainCardLinks); document.getElementById("load-json-data").innerHTML = links.join("")
 .h-0 { display: none; }
 <input id="search-filter-cards" type="text" autocomplete="off" placeholder="Type here to search"> <div id="links-list"> <div class="link-headers"><a class="mb-0">Sample Links</a></div> <div id="load-json-data"></div> <div class="card link-container"> <img class="link-img" src="../assets/links-favicons/plus.ico" /> <a class="link-title stretched-link" href="#" rel="noopener noreferrer" target="_blank" title="Plus">Plus <span class="h-0">Quick Links</span></a> </div> <div class="card link-container"> <img class="link-img" src="../assets/links-favicons/google.ico" /> <a class="link-title stretched-link" href="#" rel="noopener noreferrer" target="_blank" title="Google">Google <span class="h-0">Quick Links</span></a> </div> </div>

I have used jquery for appending, you can use javascript too.

 const dataJSON = { "linksList": [{ 'name': 'Java Bookmarks', 'title': 'Java Bookmarks', 'favicon': '../assets/links-favicons/java-bookmarks.png', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Chrono', 'title': 'Chrono', 'favicon': '../assets/links-favicons/chrono.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, { 'name': 'Kanban (May)', 'title': 'EDEN Kanban', 'favicon': '../assets/links-favicons/kanban.ico', 'url': '#', 'tags': 'Login, Logout, Log-in, Log in, Log-out Log out, Kanban board', 'linkattributes': 'rel="noopener noreferrer" target="_blank"' }, ] }; dataJSON.linksList.forEach((element) => { $('#myDiv').append(` <div><a href="${element.url}"><img style="margin-right:10px;" src="${element.favicon}"/>${element.name}</a></div> `); }) function myFunction() { var input, filter, parentDiv, childDiv, a, i, txtValue; input = document.getElementById("myInput"); filter = input.value.toUpperCase(); parentDiv = document.getElementById("myDiv"); childDiv = parentDiv.getElementsByTagName("div"); for (i = 0; i < childDiv.length; i++) { a = childDiv[i].getElementsByTagName("a")[0]; txtValue = a.textContent || a.innerText; if (txtValue.toUpperCase().indexOf(filter) > -1) { childDiv[i].style.display = ""; } else { childDiv[i].style.display = "none"; } } }
 * { box-sizing: border-box; } #myInput { background-position: 10px 12px; background-repeat: no-repeat; width: 100%; font-size: 16px; padding: 12px 20px 12px 40px; border: 1px solid #ddd; margin-bottom: 12px; } #myDiv { list-style-type: none; padding: 0; margin: 0; } #myDiv div a { border: 1px solid #ddd; margin-top: -1px; /* Prevent double borders */ background-color: #f6f6f6; padding: 12px; text-decoration: none; font-size: 18px; color: black; display: block } #myDiv div a:hover:not(.header) { background-color: #eee; }
 <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <h2>Links Search</h2> <input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name"> <div id="myDiv"> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM