0

I’m currently creating a seating plan. User’s should be able to select up to 3 available tables. After 3 tables are selected, the user should not be able to select anymore.

At the moment, the user is able to select 4 tables, which I do not want. Also, when 4 tables are selected, the user cannot unselect these tables any longer. Whereas, when the condition hasn’t been met, users can unselect tables.

Things I’ve tried:

  • Playing around with the logical operators.
  • Putting the if statement in a function and using return

const availableTables = document.querySelectorAll('.available');

for (let index = 0; index < availableTables.length; index++) {
  availableTables[index].onclick = () => {
    if (document.getElementsByClassName('active').length <= 3) {
      if (availableTables[index].classList.contains('active')) {
        availableTables[index].classList.remove('active');
      } else {
        availableTables[index].classList.add('active');
      }
    }
  }
}
.active {
  background-color: #00ccbc;
}

.seating-plan {
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 12px;
  border: solid 1px #e8ebeb;
}

.seating-plan .grey {
  border-color: #d9d9d9 !important;
}

.seating-plan .till-door {
  display: flex;
  justify-content: space-between;
  height: auto;
  color: #a9a9a9;
}

.seating-plan #section-1 {
  height: 10%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  display: flex;
}

.seating-plan #section-2 {
  height: 80%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.seating-plan #section-2 #section-2-left {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-start;
}

.seating-plan #section-2 #section-2-left .half-circle {
  width: 35px;
  height: 25px;
  border-top-left-radius: 110px;
  border-top-right-radius: 110px;
  border: solid 1px #00ccbc;
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(2) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(4) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-middle {
  height: 100%;
  width: 180px;
  justify-content: space-evenly;
  flex-wrap: wrap;
  display: flex;
  flex-direction: column;
}

.seating-plan #section-2 #section-2-middle .square-container {
  display: flex;
  justify-content: space-between;
}

.seating-plan #section-2 #section-2-right {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-end;
}

.seating-plan #section-3 {
  height: 10%;
  align-items: center;
  justify-content: center;
  display: flex;
  justify-content: space-between;
}

.seating-plan .square {
  height: 35px;
  width: 35px;
  border: solid 1px #00ccbc;
}

.seating-plan .full-circle {
  height: 35px;
  width: 35px;
  border-radius: 50%;
  border: solid 1px #00ccbc;
}
<div class="seating-plan">

  <div class="till-door">
    <p>Till</p>
    <p>Door</p>
  </div>

  <section id="section-1">
    <div class="square available"></div>
    <div class="square grey"></div>
    <div class="square available"></div>
    <div class="square available"></div>
  </section>

  <section id="section-2">
    <div id="section-2-left">
      <div class="half-circle available"></div>
      <div class="half-circle grey"></div>
      <div class="half-circle available"></div>
      <div class="half-circle available"></div>
    </div>
    <div id="section-2-middle">
      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>

      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square grey"></div>
      </div>

      <div class="square-container">
        <div class="square grey"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>


    </div>
    <div id="section-2-right">
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
    </div>
  </section>

  <section id="section-3">
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
  </section>

</div>
Barmar
  • 741,623
  • 53
  • 500
  • 612
OJM
  • 442
  • 5
  • 16

1 Answers1

2

Problem with your code on being able to select 4 is the fact you are checking if (document.getElementsByClassName('active').length <= 3) { The = is making it say if I have 3 or less currently, run the following. So that is how you are getting 4, because it is allowing it to run when 3 things are currently active.

The other issue is you are not allowing them to unselect because you are not letting them in if too many are selected. So you need to pull out the unchecking from the condition.

const availableTables = document.querySelectorAll('.available');

for (let index = 0; index < availableTables.length; index++) {
  availableTables[index].onclick = () => {

    if (availableTables[index].classList.contains('active')) {
      availableTables[index].classList.remove('active');
      return;
    }

    if (document.getElementsByClassName('active').length < 3) {
      availableTables[index].classList.add('active');
    }
  }
}
.active {
  background-color: #00ccbc;
}

.seating-plan {
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 12px;
  border: solid 1px #e8ebeb;
}

.seating-plan .grey {
  border-color: #d9d9d9 !important;
}

.seating-plan .till-door {
  display: flex;
  justify-content: space-between;
  height: auto;
  color: #a9a9a9;
}

.seating-plan #section-1 {
  height: 10%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  display: flex;
}

.seating-plan #section-2 {
  height: 80%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.seating-plan #section-2 #section-2-left {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-start;
}

.seating-plan #section-2 #section-2-left .half-circle {
  width: 35px;
  height: 25px;
  border-top-left-radius: 110px;
  border-top-right-radius: 110px;
  border: solid 1px #00ccbc;
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(2) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(4) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-middle {
  height: 100%;
  width: 180px;
  justify-content: space-evenly;
  flex-wrap: wrap;
  display: flex;
  flex-direction: column;
}

.seating-plan #section-2 #section-2-middle .square-container {
  display: flex;
  justify-content: space-between;
}

.seating-plan #section-2 #section-2-right {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-end;
}

.seating-plan #section-3 {
  height: 10%;
  align-items: center;
  justify-content: center;
  display: flex;
  justify-content: space-between;
}

.seating-plan .square {
  height: 35px;
  width: 35px;
  border: solid 1px #00ccbc;
}

.seating-plan .full-circle {
  height: 35px;
  width: 35px;
  border-radius: 50%;
  border: solid 1px #00ccbc;
}
<div class="seating-plan">

  <div class="till-door">
    <p>Till</p>
    <p>Door</p>
  </div>

  <section id="section-1">
    <div class="square available"></div>
    <div class="square grey"></div>
    <div class="square available"></div>
    <div class="square available"></div>
  </section>

  <section id="section-2">
    <div id="section-2-left">
      <div class="half-circle available"></div>
      <div class="half-circle grey"></div>
      <div class="half-circle available"></div>
      <div class="half-circle available"></div>
    </div>
    <div id="section-2-middle">
      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>

      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square grey"></div>
      </div>

      <div class="square-container">
        <div class="square grey"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>


    </div>
    <div id="section-2-right">
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
    </div>
  </section>

  <section id="section-3">
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
  </section>

</div>

You can get rid of the loops and use event delegation. With that you can check what was clicked. I would check it if is active and if it is remove it. If not active, I would query the active tables and see how many there are. If there are less than 3 add the class.

const seatingPlan = document.querySelector(".seating-plan");
seatingPlan.addEventListener("click", function (evt) {
  // find the table they clicked on
  const clickedSpot = evt.target.closest('.available');
  
  // if not avilable exit out
  if (!clickedSpot) return;
  
  // If the table was active, remove it
  if (clickedSpot.classList.contains("active")) {
    clickedSpot.classList.remove('active')
    return;
  }
  
  // make sure they have not selected more than 3 before activating it
  const currentSelected = seatingPlan.querySelectorAll(".active");
  if (currentSelected.length < 3) {
    clickedSpot.classList.add('active');    
  }

});
.active {
  background-color: #00ccbc;
}

.seating-plan {
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 12px;
  border: solid 1px #e8ebeb;
}

.seating-plan .grey {
  border-color: #d9d9d9 !important;
}

.seating-plan .till-door {
  display: flex;
  justify-content: space-between;
  height: auto;
  color: #a9a9a9;
}

.seating-plan #section-1 {
  height: 10%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  display: flex;
}

.seating-plan #section-2 {
  height: 80%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.seating-plan #section-2 #section-2-left {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-start;
}

.seating-plan #section-2 #section-2-left .half-circle {
  width: 35px;
  height: 25px;
  border-top-left-radius: 110px;
  border-top-right-radius: 110px;
  border: solid 1px #00ccbc;
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(2) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-left .half-circle:nth-child(4) {
  transform: rotate(180deg);
}

.seating-plan #section-2 #section-2-middle {
  height: 100%;
  width: 180px;
  justify-content: space-evenly;
  flex-wrap: wrap;
  display: flex;
  flex-direction: column;
}

.seating-plan #section-2 #section-2-middle .square-container {
  display: flex;
  justify-content: space-between;
}

.seating-plan #section-2 #section-2-right {
  height: 100%;
  width: 20%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-end;
}

.seating-plan #section-3 {
  height: 10%;
  align-items: center;
  justify-content: center;
  display: flex;
  justify-content: space-between;
}

.seating-plan .square {
  height: 35px;
  width: 35px;
  border: solid 1px #00ccbc;
}

.seating-plan .full-circle {
  height: 35px;
  width: 35px;
  border-radius: 50%;
  border: solid 1px #00ccbc;
}
<div class="seating-plan">

  <div class="till-door">
    <p>Till</p>
    <p>Door</p>
  </div>

  <section id="section-1">
    <div class="square available"></div>
    <div class="square grey"></div>
    <div class="square available"></div>
    <div class="square available"></div>
  </section>

  <section id="section-2">
    <div id="section-2-left">
      <div class="half-circle available"></div>
      <div class="half-circle grey"></div>
      <div class="half-circle available"></div>
      <div class="half-circle available"></div>
    </div>
    <div id="section-2-middle">
      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>

      <div class="square-container">
        <div class="square available"></div>
        <div class="square available"></div>
        <div class="square grey"></div>
      </div>

      <div class="square-container">
        <div class="square grey"></div>
        <div class="square available"></div>
        <div class="square available"></div>
      </div>


    </div>
    <div id="section-2-right">
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
      <div class="full-circle available"></div>
    </div>
  </section>

  <section id="section-3">
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
    <div class="full-circle available"></div>
  </section>

</div>
epascarello
  • 204,599
  • 20
  • 195
  • 236