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

Time:01-16

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 >
        <aside >
            <div >
                <p >Blog Categories</p>
                <button data-filter="all" >All</button>
                <button data-filter="category-a" >Show A</button>
                <button data-filter="category-b" >Show B</button>
                <button data-filter="category-c" >Show C</button>
            </div>
        </aside>

        <section >

            <div data-filter="category-a" >
                <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
                <div >
                    <h2>Title</h2>
                    <p>finance</p>
                </div>
                <p >
                    first blog description
                </p>
            </div>

            <div data-filter="category-b" >
                <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
                <div >
                    <h2>Breakfast Wrap</h2>
                    <p>Tech</p>
                </div>
                <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" >
                <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
                <div >
                    <h2>Breakfast Wrap</h2>
                    <p>lifestyle</p>
                </div>
                <p >
                    third blog description
                </p>
            </div>

            <div data-filter="category-a" >
                <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
                <div >
                    <h2>Breakfast Wrap</h2>
                    <p>finance</p>
                </div>
                <p >
                    fourth blog description
                </p>
            </div>
        </section>
    </main>

For best viewing results please open full screen

CodePudding user response:

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 >
  <aside >
    <div >
      <p >Blog Categories</p>
      <button data-filter="all" >All</button>
      <button data-filter="category-a" >Show A</button>
      <button data-filter="category-b" >Show B</button>
      <button data-filter="category-c" >Show C</button>
    </div>
  </aside>

  <section >

    <div data-filter="category-a" >
      <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
      <div >
        <h2>Title</h2>
        <p>finance</p>
      </div>
      <p >
        first blog description
      </p>
    </div>

    <div data-filter="category-b" >
      <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
      <div >
        <h2>Breakfast Wrap</h2>
        <p>Tech</p>
      </div>
      <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" >
      <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
      <div >
        <h2>Breakfast Wrap</h2>
        <p>lifestyle</p>
      </div>
      <p >
        third blog description
      </p>
    </div>

    <div data-filter="category-a" >
      <img loading="lazy" src="assets/img/300.png" alt="placeholder image">
      <div >
        <h2>Breakfast Wrap</h2>
        <p>finance</p>
      </div>
      <p >
        fourth blog description
      </p>
    </div>
  </section>
</main>

  • Related