Home > Enterprise >  I am having a problem with Query selectors for this project website
I am having a problem with Query selectors for this project website

Time:06-28

So I am learning web dev, and I am a beginner. I have learned a tiny bit about DOM manipulation and I am facing a small issue with a click event.

The HTML CSS and JS code in codepen

Please click on the pizza image. When you click on it, the box shadow should remain even after you do not hover over the pizza and the gray link bar bellow is now yellow even when you don't hover over it. Click back on it and it returns to normal, neat!

Please now click on the pavlova (the sweet pinkish dessert). It doesn't work even though it shares the exact same css classes and everything when it comes to style.

I hope I have described my problem properly. If anything is not clear I will explain more. I have been on this for a while and I really don't know how to fix it. I will include the code here as well but everything is on code pen above, whichever is preferred.

const theFoodImg = document.querySelector('.food-img');
const recipeLink = document.querySelector('.recipe-link');
const linkIcon = document.querySelector('.fa-link');
const pinTopBar = document.querySelector('.fa-thumbtack');
const topBar = document.querySelector('#top-bar');
const pinColor = document.querySelector('.fa-thumbtack');


theFoodImg.addEventListener('click', function() {
  if (theFoodImg.classList.contains('active')) {
    theFoodImg.classList.remove('active');
    theFoodImg.classList.remove('food-hover');
    theFoodImg.classList.add('food-img');
    recipeLink.classList.add('recipe-link');
    recipeLink.classList.remove('click');
    linkIcon.classList.add('white-link')
    linkIcon.classList.remove('blue-link')
  } else {
    theFoodImg.classList.remove('food-img');
    theFoodImg.classList.add('active');
    recipeLink.classList.remove('recipe-link');
    recipeLink.classList.add('click');
    linkIcon.classList.remove('white-link')
    linkIcon.classList.add('blue-link')

  }
})

theFoodImg.addEventListener('mouseenter', function() {
  if (theFoodImg.classList.contains('active') !== true) {
    theFoodImg.classList.add('food-hover');
  }
})


if (topBar.classList.contains('fix')) {
  pinColor.style.color = 'goldenrod';
}
pinTopBar.addEventListener('click', function() {
  if (topBar.classList.contains('fix') !== true) {
    topBar.classList.add('fix');
    pinColor.style.color = 'goldenrod';
  } else {
    topBar.classList.remove('fix');
    pinColor.style.color = 'black';
  }
})
/* css reset */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  text-decoration: none;
}

body {
  margin: 0;
  padding: 0;
}

a {
  color: black;
  text-decoration: none;
}

hr {
  width: 80%;
  margin: 0 auto;
  background-color: black;
  box-shadow: 0 0 15px gold;
}


/* banner and title styles */

div#banner {
  background: url(https://i.ibb.co/MgBrNdY/background-img.jpg);
  box-shadow: inset 0 0 0 9000em rgba(68, 68, 68, 0.5);
  background-size: cover;
  height: 50vh;
  /* change later for media queries */
}


/* title style */

h1#large-screen-title {
  color: goldenrod;
  text-align: center;
  padding: 0.5em;
  font-size: 4em;
}

div#top-bar {
  background-color: rgb(255, 250, 234);
  height: min-content;
}

.fix {
  position: fixed;
  height: 15%;
  right: 0;
  left: 0;
  top: 0;
  box-shadow: 0 0 20px goldenrod;
}

img#odin-logo {
  height: 5em;
}

i.fa-thumbtack {
  float: right;
  padding: 1em;
}

i.fa-thumbtack:hover {
  cursor: pointer;
}

@media only screen and (min-width: 700px) {
  div#banner {
    height: 80vh;
  }
  h1#title-index {
    height: 60vh;
    color: transparent;
    border: 0px solid white;
  }
  div#top-bar {
    text-align: center;
  }
}


/* recipe card styles */

div#recipe-card-container {
  padding-top: 5em;
  padding-left: 0.5em;
  padding-right: 0.5em;
  display: grid;
  grid-template-columns: 1fr;
  justify-content: center;
  align-items: center;
  gap: 2em;
}


/*each recipe card */

div#recipe-card-container>div.each-recipe {
  display: grid;
  gap: 2em;
  margin-bottom: 5em;
  justify-content: center;
}

div#recipe-card-container div.recipe-img {
  /* background-color: red; */
  width: 100%;
  height: 50vh;
  border-radius: 3px;
  transition: 450ms;
}


/*recipe link within each card */

div.recipe-link {
  background-color: lightgray;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  transition: 450ms;
  border-radius: 0.3em;
}

div.recipe-link:hover {
  background-color: #eece1a;
  transition: 450ms;
}


/* when clicked add this style */

.click {
  background-color: #eece1a;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  border-radius: 0.3em;
  transition: 450ms;
  width: 100%;
  margin: 0 auto;
}


/**/

i.fa-link {
  float: left;
}

div.recipe-link:hover>i.fa-link {
  color: rgb(0, 0, 255, 0.5);
}


/*when clicked, target i.fa-link color */

.white-link {
  color: white;
}

.blue-link {
  color: rgb(0, 0, 255, 0.5);
}


/* food image style on card */

.food-img {
  height: 100%;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}

img.food-img {
  width: 100%;
}

img.food-hover:hover,
.active {
  box-shadow: 0 0 20px rgb(189, 80, 12);
  height: 105%;
  object-fit: cover;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}


/*grey bar with copyright*/

div.copy {
  background-color: rgba(0, 0, 0, 0.54);
  margin-top: 2em;
  padding: 2em;
  color: white;
  text-align: center;
}

@media only screen and (min-width: 1020px) {
  div#recipe-card-container {
    padding-left: 0;
    padding-right: 0;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 2em;
    margin-top: 2em;
    box-shadow: inset 0 500px rgb(85, 63, 63);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="stylesheet" href="../style.css" />
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Odin Recipes</title>
</head>

<body>
  <div id="banner">
    <div id="top-bar" >
      <a href="https://www.theodinproject.com/"><img src="https://i.ibb.co/7nhgfNJ/odin-logo.png" alt="" id="odin-logo" /></a>
      <i ></i>
    </div>
  </div>
  <br />
  <br />
  <hr />
  <h1 id="large-screen-title">Odin Recipes</h1>
  <br /><br />
  <hr />


  <div id="recipe-card-container">


    <div >
      <div >
        <img src="https://i.ibb.co/mDCCZTW/pizza.jpg" alt=""  />
      </div>
      <a href="/recipes/pizza.html">
        <div >
          <i ></i>Click here for Pizza Recipe
        </div>
      </a>
    </div>


    <div >
      <div >
        <img src="https://i.ibb.co/5cQCFWP/pavlova.png" alt=""  />
      </div>
      <a href="/recipes/pavlova.html">
        <div >
          <i ></i>Click here for Pavlova Recipe
        </div>
      </a>
    </div>

    <div >
      <div >
        <img src="/recipes/images/" alt=""  />
      </div>
      <a href="/recipes/">
        <div >
          <i ></i>Click here for Pavlova Recipe
        </div>
      </a>
    </div>

  </div>

  <div >Copyright &copy; 2022</div>





  <script src="https://kit.fontawesome.com/fb94170dc7.js" crossorigin="anonymous"></script>
  <script src="app.js"></script>
</body>

</html>

CodePudding user response:

Check out the below snippet. i have updated theFoodImg variable to theFoodImgs and leveraged querySelectorAll to get a node list of all the .food-img class elements. Then use a foreach loop on the nodelist to loop it and add your listeners. You may want to update more of your variables from querySelector to querySelectorAll. I have done this one to get you headed down the correct path.

const theFoodImgs = document.querySelectorAll('.food-img'),
  recipeLink = document.querySelector('.recipe-link'),
  linkIcon = document.querySelector('.fa-link'),
  pinTopBar = document.querySelector('.fa-thumbtack'),
  topBar = document.querySelector('#top-bar'),
  pinColor = document.querySelector('.fa-thumbtack');

theFoodImgs.forEach(function (el) {
  el.addEventListener('click', function() {
    if(el.classList.contains('active')){
            el.classList.remove('active');
            el.classList.remove('food-hover');
            el.classList.add('food-img');
            recipeLink.classList.add('recipe-link');
        recipeLink.classList.remove('click');
        linkIcon.classList.add('white-link')
        linkIcon.classList.remove('blue-link')
    } else {
        el.classList.remove('food-img');
        el.classList.add('active');
        recipeLink.classList.remove('recipe-link');
        recipeLink.classList.add('click');
        linkIcon.classList.remove('white-link')
        linkIcon.classList.add('blue-link')

    }
  });
  el.addEventListener('mouseenter', function(){
      if (el.classList.contains('active') !== true) {
          el.classList.add('food-hover');
      }
  })
});


if(topBar.classList.contains('fix')) {
    pinColor.style.color = 'goldenrod';
}
pinTopBar.addEventListener('click', function() {
    if(topBar.classList.contains('fix') !== true) {
        topBar.classList.add('fix');
        pinColor.style.color = 'goldenrod';
  }
  else  {
    topBar.classList.remove('fix');
    pinColor.style.color = 'black';
    }
})
/* css reset */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  text-decoration: none;
}
body {
  margin: 0;
  padding: 0;
}
a {
  color: black;
  text-decoration: none;
}

hr {
  width: 80%;
  margin: 0 auto;
  background-color: black;
  box-shadow: 0 0 15px gold;
}
/* banner and title styles */
div#banner {
  background: url(https://i.ibb.co/MgBrNdY/background-img.jpg);
  box-shadow: inset 0 0 0 9000em rgba(68, 68, 68, 0.5);
  background-size: cover;
  height: 50vh; /* change later for media queries */
}

/* title style */

h1#large-screen-title {
  color: goldenrod;
  text-align: center;
  padding: 0.5em;
  font-size: 4em;
}

div#top-bar {
  background-color: rgb(255, 250, 234);
  height: min-content;
}
.fix {
  position: fixed;
  height: 15%;
  right: 0;
  left: 0;
  top: 0;
  box-shadow: 0 0 20px goldenrod;
}
img#odin-logo {
  height: 5em;
}
i.fa-thumbtack {
  float: right;
  padding: 1em;
}
i.fa-thumbtack:hover {
  cursor: pointer;
}
@media only screen and (min-width: 700px) {
  div#banner {
    height: 80vh;
  }
  h1#title-index {
    height: 60vh;
    color: transparent;
    border: 0px solid white;
  }
  div#top-bar {
    text-align: center;
  }
}

/* recipe card styles */

div#recipe-card-container {
  padding-top: 5em;
  padding-left: 0.5em;
  padding-right: 0.5em;
  display: grid;
  grid-template-columns: 1fr;
  justify-content: center;
  align-items: center;
  gap: 2em;
}

/*each recipe card */
div#recipe-card-container > div.each-recipe {
  display: grid;
  gap: 2em;
  margin-bottom: 5em;
  justify-content: center;
}

div#recipe-card-container div.recipe-img {
  /* background-color: red; */
  width: 100%;
  height: 50vh;
  border-radius: 3px;
  transition: 450ms;
}

/*recipe link within each card */
div.recipe-link {
  background-color: lightgray;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  transition: 450ms;
  border-radius: 0.3em;
}
div.recipe-link:hover {
  background-color: #eece1a;
  transition: 450ms;
}

/* when clicked add this style */
.click {
  background-color: #eece1a;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  border-radius: 0.3em;
  transition: 450ms;
  width: 100%;
  margin: 0 auto;
}
/**/

i.fa-link {
  float: left;
}
div.recipe-link:hover > i.fa-link {
  color: rgb(0, 0, 255, 0.5);
}
/*when clicked, target i.fa-link color */
.white-link {
  color: white;
}
.blue-link {
  color: rgb(0, 0, 255, 0.5);
}


/* food image style on card */
.food-img {
  height: 100%;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}
img.food-img {
  width: 100%;
} 
img.food-hover:hover,
.active {
  box-shadow: 0 0 20px rgb(189, 80, 12);
  height: 105%;
  object-fit: cover;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}

/*grey bar with copyright*/
div.copy {
  background-color: rgba(0, 0, 0, 0.54);
  margin-top: 2em;
  padding: 2em;
  color: white;
  text-align: center;
}

@media only screen and (min-width: 1020px) {
  div#recipe-card-container {
    padding-left: 0;
    padding-right: 0;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 2em;
    margin-top: 2em;
    box-shadow: inset 0 500px rgb(85, 63, 63);
  }

}
<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="../style.css" />
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Odin Recipes</title>
  </head>
  <body>
    <div id="banner">
      <div id="top-bar" >
        <a href="https://www.theodinproject.com/"
          ><img src="https://i.ibb.co/7nhgfNJ/odin-logo.png" alt="" id="odin-logo"
        /></a>
        <i ></i>
      </div>
    </div>
    <br />
    <br />
    <hr />
    <h1 id="large-screen-title">Odin Recipes</h1>
    <br /><br />
    <hr />


    <div id="recipe-card-container">
      
      
      <div >
        <div >
          <img
            src="https://i.ibb.co/mDCCZTW/pizza.jpg"
            alt=""
            
          />
        </div>
        <a href="/recipes/pizza.html">
          <div >
            <i ></i>Click here for Pizza
            Recipe
          </div>
        </a>
      </div>
      

      <div >
        <div >
          <img
            src="https://i.ibb.co/5cQCFWP/pavlova.png"
            alt=""
            
          />
        </div>
        <a href="/recipes/pavlova.html">
          <div >
            <i ></i>Click here for Pavlova
            Recipe
          </div>
        </a>
      </div>

      <div >
        <div >
          <img
            src="/recipes/images/"
            alt=""
            
          />
        </div>
        <a href="/recipes/">
          <div >
            <i ></i>Click here for Pavlova
            Recipe
          </div>
        </a>
      </div>

      </div>

      <div >Copyright &copy; 2022</div>
  




    <script
      src="https://kit.fontawesome.com/fb94170dc7.js"
      crossorigin="anonymous"
    ></script>
    <script src="app.js"></script>
  </body>
</html>

CodePudding user response:

I simplified the process to not query ANY loops. Instead I'm assigning the event handler to the parent of the recipes. Then I look for the active element and REMOVE the active class from the recipe itself. Instead of adding/removing classes from each element, I simply add an active class to the recipe parent and use CSS to modify the children of the active class.

const recipes = document.querySelector("#recipe-card-container")

recipes.addEventListener("click", function(el) {
  let target = el.target;
  if (target.className.indexOf("food-img") > -1) {
    let active = document.querySelector(".each-recipe.active");
    if (active) {
      active.classList.remove("active");
    }
    target.parentNode.parentNode.classList.add("active");
  }
});
/* css reset */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  text-decoration: none;
}

body {
  margin: 0;
  padding: 0;
}

a {
  color: black;
  text-decoration: none;
}

hr {
  width: 80%;
  margin: 0 auto;
  background-color: black;
  box-shadow: 0 0 15px gold;
}


/* banner and title styles */

div#banner {
  background: url(https://i.ibb.co/MgBrNdY/background-img.jpg);
  box-shadow: inset 0 0 0 9000em rgba(68, 68, 68, 0.5);
  background-size: cover;
  height: 50vh;
  /* change later for media queries */
}


/* title style */

h1#large-screen-title {
  color: goldenrod;
  text-align: center;
  padding: 0.5em;
  font-size: 4em;
}

div#top-bar {
  background-color: rgb(255, 250, 234);
  height: min-content;
}

.fix {
  position: fixed;
  height: 15%;
  right: 0;
  left: 0;
  top: 0;
  box-shadow: 0 0 20px goldenrod;
}

img#odin-logo {
  height: 5em;
}

i.fa-thumbtack {
  float: right;
  padding: 1em;
}

i.fa-thumbtack:hover {
  cursor: pointer;
}

@media only screen and (min-width: 700px) {
  div#banner {
    height: 80vh;
  }
  h1#title-index {
    height: 60vh;
    color: transparent;
    border: 0px solid white;
  }
  div#top-bar {
    text-align: center;
  }
}


/* recipe card styles */

div#recipe-card-container {
  padding-top: 5em;
  padding-left: 0.5em;
  padding-right: 0.5em;
  display: grid;
  grid-template-columns: 1fr;
  justify-content: center;
  align-items: center;
  gap: 2em;
}


/*each recipe card */

div#recipe-card-container>div.each-recipe {
  display: grid;
  gap: 2em;
  margin-bottom: 5em;
  justify-content: center;
}

div#recipe-card-container div.recipe-img {
  /* background-color: red; */
  width: 100%;
  height: 50vh;
  border-radius: 3px;
  transition: 450ms;
}


/*recipe link within each card */

div.recipe-link {
  background-color: lightgray;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  transition: 450ms;
  border-radius: 0.3em;
}

div.recipe-link:hover {
  background-color: #eece1a;
  transition: 450ms;
}


/* when clicked add this style */

.active .recipe-link {
  background-color: #eece1a;
  text-align: center;
  padding-top: 1em;
  padding: 0.5em;
  border-radius: 0.3em;
  transition: 450ms;
  width: 100%;
  margin: 0 auto;
}


/**/

i.fa-link {
  float: left;
}

div.recipe-link:hover>i.fa-link {
  color: rgb(0, 0, 255, 0.5);
}


/*when clicked, target i.fa-link color */

.recipe-link i {
  color: white;
}

.each-recipe.active i {
  color: rgb(0, 0, 255, 0.5);
}


/* food image style on card */

.food-img {
  height: 100%;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}

img.food-img {
  width: 100%;
}

img.food-hover:hover,
.each-recipe.active img {
  box-shadow: 0 0 20px rgb(189, 80, 12);
  height: 105%;
  object-fit: cover;
  border-radius: 50%;
  border: 4px solid rgba(189, 80, 12, 0.637);
  transition: 450ms;
  cursor: pointer;
}


/*grey bar with copyright*/

div.copy {
  background-color: rgba(0, 0, 0, 0.54);
  margin-top: 2em;
  padding: 2em;
  color: white;
  text-align: center;
}

@media only screen and (min-width: 1020px) {
  div#recipe-card-container {
    padding-left: 0;
    padding-right: 0;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 2em;
    margin-top: 2em;
    box-shadow: inset 0 500px rgb(85, 63, 63);
  }
}
<div id="recipe-card-container">


  <div >
    <div >
      <img src="https://i.ibb.co/mDCCZTW/pizza.jpg" alt=""  />
    </div>
    <a href="/recipes/pizza.html">
      <div >
        <i ></i>Click here for Pizza Recipe
      </div>
    </a>
  </div>


  <div >
    <div >
      <img src="https://i.ibb.co/5cQCFWP/pavlova.png" alt=""  />
    </div>
    <a href="/recipes/pavlova.html">
      <div >
        <i ></i>Click here for Pavlova Recipe
      </div>
    </a>
  </div>

  <div >
    <div >
      <img src="/recipes/images/" alt=""  />
    </div>
    <a href="/recipes/">
      <div >
        <i ></i>Click here for Pavlova Recipe
      </div>
    </a>
  </div>

</div>

<div >Copyright &copy; 2022</div>





<script src="https://kit.fontawesome.com/fb94170dc7.js" crossorigin="anonymous"></script>

  • Related