Home > Software design >  Problem with my alerts, first alert closes normally but others don't close
Problem with my alerts, first alert closes normally but others don't close

Time:09-30

I am creating an alert system for my website, and the server should return more than one alert, but i don't know how to make the close button work for each alert, im my code, only the first alert close but the other ones does nothing. Can anyone help me?

<div id="alert" class="info showAlert">
    <div id="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button id="close">x</button>
  </div>

$('#close').click(function(){
    $("#alert").removeClass("showAlert");
  $("#alert").addClass("hideAlert");
  setTimeout(() => {
    $("#alert").remove()
  }, 500);
});

https://jsfiddle.net/joaopcos/em8aLbdh/27/

CodePudding user response:

In HTML, ids need to be unique. While there are numerous reasons for this, the issue you're experiencing stems from your jQuery attempting to target a unique id that is repeated multiple times (in your jsfiddle example). Instead, convert your ids to classes, and target the closest alert to whichever close button was clicked.

$(".close").click(function() {
  const thisAlert = $(this).closest(".alert");

  thisAlert
    .removeClass("showAlert")
    .addClass("hideAlert");
  setTimeout(() => {
    thisAlert.remove()
  }, 500);
});
@import url('https://fonts.googleapis.com/css2?family=Exo:ital,wght@0,400;0,500;1,700&display=swap');
#alert-container {
  position: fixed;
  top: 84px;
  right: 12px;
}

.alert {
  display: flex;
  max-width: 540px;
  margin-left: 12px;
  margin-bottom: 10px;
  border-radius: 5px;
  padding: 0 12px 0 12px;
}

.alert.showAlert {
  animation: showAlert 500ms ease forwards;
}

@keyframes showAlert {
  0% {
    transform: translateX(110%);
  }
  100% {
    transform: translateX(0%);
  }
}

.alert.hideAlert {
  animation: hideAlert 500ms ease forwards;
}

@keyframes hideAlert {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(110%);
  }
}

.content {
  display: flex;
  align-items: center;
  font-size: 20px;
  font-weight: 500;
}

.content>svg {
  width: 32px;
  height: 32px;
  margin-right: 16px;
}

.close {
  position: relative;
  left: 12px;
  border-radius: 0 5px 5px 0;
  border: none;
  cursor: pointer;
}

.close>svg {
  width: 24px;
  height: 24px;
  margin: 0 12px 0 12px;
}

.error {
  background-color: #FFE1E3;
  border-left: 8px solid #FF465D;
  color: #FF4553;
}

.error>button {
  background-color: #FFB9BE;
  color: #FF4553;
}

.info {
  background-color: #D6F0FD;
  border-left: 8px solid #71C7F8;
  color: #3DB6FF;
}

.info>button {
  background-color: #A8DDFD;
  color: #3DB6FF;
}

.success {
  background-color: #C5F3D7;
  border-left: 8px solid #2AD56F;
  color: #20AF5D;
}

.success>button {
  background-color: #94EAB9;
  color: #20AF5D;
}

.warning {
  background-color: #FFEAC5;
  border-left: 8px solid #FFC04C;
  color: #F19B00;
}

.warning>button {
  background-color: #FFDCA1;
  color: #F19B00;
}

@media only screen and (max-width: 540px) {
  .content {
    font-size: 16px;
  }
  .content>svg {
    width: 24px;
    height: 24px;
  }
  .close>svg {
    width: 18px;
    height: 18px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="alert-container">
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
</div>

jsFiddle

CodePudding user response:

Your code has many of the same IDs. The ID attribute is meant to be a unique ID all throughout the entire HTML document. So your jQuery tries to remove just the first ID and that's why only the first ID works.

For starters, change all of your #alerts and #closes to classes in the HTML and the CSS (for mere styling purposes and a cleaner document). And then for your jQuery, in order to avoid having to come up with a new ID every single time, apply an onclick listener to each member of the class, and then proceed to remove the parent of the clicked element, that way it will only remove the alert that contains the x.

Here is an example of what I mean:
HTML:

<div id="alert-container">
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
  <div class="alert info showAlert">
    <div class="content">
      <i class="fas fa-exclamation-circle"></i>
      <p>Warning: This is a warning alert!</p>
    </div>
    <button class="close">x</button>
  </div>
</div>

CSS: (just an excerpt - apply this everywhere)

.alert{ /*Instead of #alert*/
  display: flex;
  max-width: 540px;
  margin-left: 12px;
  margin-bottom: 10px;
  border-radius: 5px;
  padding: 0 12px 0 12px;
}

Basically change all of your #alerts #contents and #closes to .alert, .content, and .close in your CSS

And for your jQuery, something like this is what I was talking about:
JavaScript:

$(".close").each((index, closeButton) => {
    //In your HTML the immediate parent of the button is the alert so this is how we will access it for each button since they are all different
    var alert = $(closeButton).parent();
    $(closeButton).click(function() {
        $(alert).removeClass("showAlert");
        $(alert).addClass("hideAlert");
        setTimeout(() => {
            $(alert).remove()
        }, 500);
    });
});

That should work but I haven't tested it myself

CodePudding user response:

First thing i noticed that you are using multiple id attributes with same name: alert and close. This is not good from HTML spec side. See this. And when you do this with jquery i guess it is only taking first element and does whatever you say only on that element.
My solution is like below. Please add your close button elements class 'close' to get this working.

$('.info .close').click(function(){
  $(this).parent().removeClass("showAlert");
  $(this).parent().addClass("hideAlert");
});
  • Related