简体   繁体   中英

Javascript Filter finds all data attributes but not their respective DOM elements

I built a filter that will find only one DOM element but not more than one. However, the filter does find all the data attributes for each respective DOM element.

I am wondering why all DOM elements are not being found, but all their data attributes are? For example, the arrays of categories which are the data attributes are correctly built, but their respective DOM elements are not being found if there exist more than one.

In error, there is only one blog post per category which is not practical because it would be best to see multiple blog post for any given category.

 "use strict"; const filterBtns = Array.from(document.querySelectorAll("button.btn")); const itemTag = Array.from(document.querySelectorAll("div.item")); function applyFilter() { filterBtns.forEach((btn, idx) => { btn.addEventListener("click", () => { if (idx === 0) { itemTag.forEach(item => { item.style.border = 'solid 2px red'; }) } else { itemTag.forEach(item => { item.style.border = 'solid 2px transparent'; }) filterValues(itemTag, btn) } }) }) } /* Takes an array and button attributes as parameters Builds a new array of the items attributes and filters the button clicked attribute. Loops over the itemTag array and if they match change the color of the border. */ function filterValues(arr, btnData) { let attributeArray = []; let btnAttribute = btnData.getAttribute('data-filter'); for (let index = 0; index <= arr.length - 1; index++) { attributeArray.push(arr[index].getAttribute('data-filter')); } // builds filtered array const result = attributeArray.filter((value => { return value.trim().includes(btnAttribute); })) itemTag.forEach(item => { let itemAttribute = item.getAttribute('data-filter'); if (itemAttribute.includes(result)) { item.style.border = '2px solid blue'; console.log(item); } }) console.log("Result Array ", result); } applyFilter();
 * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } /* CSS VARIABLES */:root { --blog-primary-color: #A4BEF3; --blog-secondary-color: whitesmoke; --blog-primary-text-color: #000000; --blog-secondary-text-color: #fff; --blog-primary-padding: 2em; --blog-primary-margin: 2rem; --blog-section-padding: 1em; } /* General Settings */ button { border: none; margin: 0; } a { text-decoration: none; } /* Render CSS */ body { font-family: system-ui, serif; font-size: 32px; line-height: 1.5; background-color: #f9f0de; color: #1f2839; } /* Navigation Bar Styling */ nav { display: flex; justify-content: space-between; align-items: center; padding-left: var(--blog-primary-padding); padding-right: var(--blog-primary-padding); padding-top: 0.7rem; background-color: var(--blog-primary-color); } nav h1 { font-size: 24px; font-weight: bolder; } nav a.login-link { font-size: 18px; color: #000000; font-weight: bold; } /* Main Section Styling *****/ main { background-color: var(--blog-secondary-color); height: 100%; display: flex; justify-content: space-around; } main aside { height: 100%; position: sticky; top: 0; left: 0; width: 25%; } /* Button Aside Div */ main aside div { display: flex; flex-direction: column; justify-content: space-around; align-items: flex-start; /* border: 2px solid red; */ height: 500px; padding: var(--blog-primary-padding); } main aside div p.button-p { color: red; font-size: 18px; font-weight: bolder; color: #1f2839; } button.btn { color: #1f2839; font-size: 16px; background-color: whitesmoke; transition: background-color 300ms ease-in-out; width: 100%; text-align: left; border-radius: 5px; font-weight: bold; padding: 0.4rem 1rem 0.4rem 1rem; } button.btn:hover { background-color: var(--blog-primary-color); cursor: pointer; } /* Section Blog Grid Styling */ section.blog-grid { display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); gap: 1rem; margin-top: 0.7rem; } div.item { width: 360px; border: 2px solid transparent; } div.item img { width: 100%; object-fit: cover; } div.blog-title { display: flex; justify-content: space-between; } div.blog-title h2, div.blog-title p { font-size: 24px; color: var(--blog-primary-text-color); } p.blog-p { color: var(--blog-primary-text-color); font-size: 18px; font-weight: 400; } /* Add MOBILE SCREEN MEDIA QUERIES */
 <main class="index-main"> <aside class="categories"> <div class="button-div"> <p class="button-p">Blog Categories</p> <button data-filter="all" class="btn">All</button> <button data-filter="category-a" class="btn">Show A</button> <button data-filter="category-b" class="btn">Show B</button> <button data-filter="category-c" class="btn">Show C</button> </div> </aside> <section class="blog-grid"> <div data-filter="category-a" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Title</h2> <p>finance</p> </div> <p class="blog-p"> first blog description </p> </div> <div data-filter="category-b" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>Tech</p> </div> <p class="blog-p"> second blog description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Asperiores voluptates, facilis quas rem officiis sapiente fugit, Cumque adipisci quam optio repellendus neque voluptatum? nam ut consequuntur blanditiis possimus quae veniam. </p> </div> <div data-filter="category-c" class="category-c item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>lifestyle</p> </div> <p class="blog-p"> third blog description </p> </div> <div data-filter="category-a" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>finance</p> </div> <p class="blog-p"> fourth blog description </p> </div> </section> </main>

For best viewing results please open full screen

The elements are being found. The problem lies in if (itemAttribute.includes(result)) { where you pass an array result into the includes method, which expects a string.

Because it expects a string it will try to convert your result array into a string, which works if you have a single value, but with two items in the result array, you get a bad result.

I believe that your logic should be the other way around where you should check if itemAttribute exists in the result array.

if (result.includes(itemAttribute)) {

 "use strict"; const filterBtns = Array.from(document.querySelectorAll("button.btn")); const itemTag = Array.from(document.querySelectorAll("div.item")); function applyFilter() { filterBtns.forEach((btn, idx) => { btn.addEventListener("click", () => { if (idx === 0) { itemTag.forEach(item => { item.style.border = 'solid 2px red'; }) } else { itemTag.forEach(item => { item.style.border = 'solid 2px transparent'; }) filterValues(itemTag, btn) } }) }) } /* Takes an array and button attributes as parameters Builds a new array of the items attributes and filters the button clicked attribute. Loops over the itemTag array and if they match change the color of the border. */ function filterValues(arr, btnData) { let attributeArray = []; let btnAttribute = btnData.getAttribute('data-filter'); for (let index = 0; index <= arr.length - 1; index++) { attributeArray.push(arr[index].getAttribute('data-filter')); } // builds filtered array const result = attributeArray.filter((value => { return value.trim().includes(btnAttribute); })) itemTag.forEach(item => { let itemAttribute = item.getAttribute('data-filter'); if (result.includes(itemAttribute)) { item.style.border = '2px solid blue'; console.log(item); } }) console.log("Result Array ", result); } applyFilter();
 * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } /* CSS VARIABLES */:root { --blog-primary-color: #A4BEF3; --blog-secondary-color: whitesmoke; --blog-primary-text-color: #000000; --blog-secondary-text-color: #fff; --blog-primary-padding: 2em; --blog-primary-margin: 2rem; --blog-section-padding: 1em; } /* General Settings */ button { border: none; margin: 0; } a { text-decoration: none; } /* Render CSS */ body { font-family: system-ui, serif; font-size: 32px; line-height: 1.5; background-color: #f9f0de; color: #1f2839; } /* Navigation Bar Styling */ nav { display: flex; justify-content: space-between; align-items: center; padding-left: var(--blog-primary-padding); padding-right: var(--blog-primary-padding); padding-top: 0.7rem; background-color: var(--blog-primary-color); } nav h1 { font-size: 24px; font-weight: bolder; } nav a.login-link { font-size: 18px; color: #000000; font-weight: bold; } /* Main Section Styling *****/ main { background-color: var(--blog-secondary-color); height: 100%; display: flex; justify-content: space-around; } main aside { height: 100%; position: sticky; top: 0; left: 0; width: 25%; } /* Button Aside Div */ main aside div { display: flex; flex-direction: column; justify-content: space-around; align-items: flex-start; /* border: 2px solid red; */ height: 500px; padding: var(--blog-primary-padding); } main aside div p.button-p { color: red; font-size: 18px; font-weight: bolder; color: #1f2839; } button.btn { color: #1f2839; font-size: 16px; background-color: whitesmoke; transition: background-color 300ms ease-in-out; width: 100%; text-align: left; border-radius: 5px; font-weight: bold; padding: 0.4rem 1rem 0.4rem 1rem; } button.btn:hover { background-color: var(--blog-primary-color); cursor: pointer; } /* Section Blog Grid Styling */ section.blog-grid { display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); gap: 1rem; margin-top: 0.7rem; } div.item { width: 360px; border: 2px solid transparent; } div.item img { width: 100%; object-fit: cover; } div.blog-title { display: flex; justify-content: space-between; } div.blog-title h2, div.blog-title p { font-size: 24px; color: var(--blog-primary-text-color); } p.blog-p { color: var(--blog-primary-text-color); font-size: 18px; font-weight: 400; } /* Add MOBILE SCREEN MEDIA QUERIES */
 <main class="index-main"> <aside class="categories"> <div class="button-div"> <p class="button-p">Blog Categories</p> <button data-filter="all" class="btn">All</button> <button data-filter="category-a" class="btn">Show A</button> <button data-filter="category-b" class="btn">Show B</button> <button data-filter="category-c" class="btn">Show C</button> </div> </aside> <section class="blog-grid"> <div data-filter="category-a" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Title</h2> <p>finance</p> </div> <p class="blog-p"> first blog description </p> </div> <div data-filter="category-b" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>Tech</p> </div> <p class="blog-p"> second blog description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Asperiores voluptates, facilis quas rem officiis sapiente fugit, Cumque adipisci quam optio repellendus neque voluptatum? nam ut consequuntur blanditiis possimus quae veniam. </p> </div> <div data-filter="category-c" class="category-c item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>lifestyle</p> </div> <p class="blog-p"> third blog description </p> </div> <div data-filter="category-a" class="item"> <img loading="lazy" src="assets/img/300.png" alt="placeholder image"> <div class="blog-title"> <h2>Breakfast Wrap</h2> <p>finance</p> </div> <p class="blog-p"> fourth blog description </p> </div> </section> </main>

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