0

I use an HTML calendar where I can select multiple date ranges. How can I prevent time periods from overlap?

  • First click select first day

  • Second click select range (must be AFTER the first click day)

  • Third click select next first day

  • Fourth click select next range

My idea is to do it via the index(), but I don't know how....

I am glad about tips and help. I can't get any further on my own.

$("td.day").click(function() {

    if ($("td.firstClick").length == 0 && $(this).hasClass("reserved") == false) {
        $(this).addClass("firstClick");
    }
    
    if ($("td.firstClick").length > 0 && $(this).hasClass("firstClick") == false) {
        var tds = $("td.day");
        var firstClick = $(".firstClick");
        var firstClickIndex = tds.index(firstClick);
        var currentIndex = tds.index(this);
        
        tds.filter(function() {
            var idx = tds.index(this);
            return idx > firstClickIndex && idx < currentIndex;
            }).addClass("reserved");
    
        $(".firstClick").addClass("checkin").removeClass("firstClick");
        $(this).addClass("checkout");
    }
});
table {
  border-collapse: collapse;
}
table tr td {
  width: 14%;
}
table tr td:hover {
  cursor: pointer;
}
.firstClick {
  background: green;
}
.checkin {
  background: yellow;
}
.checkout {
  background: red;
}
.reserved {
  background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
  <tr>
    <td colspan="7"><b>2016</b>
    </td>
  </tr>
  <tr>
    <td colspan="7"><i>November</i>
    </td>
  </tr>
  <tr>
    <th>mon</th>
    <th>tue</th>
    <th>wed</th>
    <th>thu</th>
    <th>fri</th>
    <th>sat</th>
    <th>sun</th>
  </tr>
  <tr>
    <td></td>
    <td class="day">1</td>
    <td class="day">2</td>
    <td class="day">3</td>
    <td class="day">4</td>
    <td class="day">5</td>
    <td class="day">6</td>
  </tr>
  <tr>
    <td class="day">7</td>
    <td class="day">8</td>
    <td class="day">9</td>
    <td class="day">10</td>
    <td class="day">11</td>
    <td class="day">12</td>
    <td class="day">13</td>
  </tr>
  <tr>
    <td class="day">14</td>
    <td class="day">15</td>
    <td class="day">16</td>
    <td class="day">17</td>
    <td class="day">18</td>
    <td class="day">19</td>
    <td class="day">20</td>
  </tr>
  <tr>
    <td class="day">21</td>
    <td class="day">22</td>
    <td class="day">23</td>
    <td class="day">24</td>
    <td class="day">25</td>
    <td class="day">26</td>
    <td class="day">27</td>
  </tr>
  <tr>
    <td class="day">28</td>
    <td class="day">29</td>
    <td class="day">30</td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</table>

0

1 Answer 1

0

Before you add the reserved class to the range of days, check if any of them are already reserved.

$("td.day").click(function() {

  if ($("td.firstClick").length == 0 && !$(this).is(".reserved, .checkin, .checkout")) {
    $(this).addClass("firstClick");
    return;
  }

  // Click again to toggle first date
  if ($(this).hasClass("firstClick")) {
    $(this).removeClass("firstClick");
    return;
  }

  if ($("td.firstClick").length > 0 && !$(this).hasClass("firstClick")) {
    var tds = $("td.day");
    var firstClick = $(".firstClick");
    var firstClickIndex = tds.index(firstClick);
    var currentIndex = tds.index(this);

    if (currentIndex < firstClickIndex) {
      alert("Checkout has to be after checkin");
      return;
    }

    var range = tds.filter(function() {
      var idx = tds.index(this);
      return idx > firstClickIndex && idx < currentIndex;
    });
    if (range.filter(".reserved, .checkin, .checkout").length > 0) {
      alert("Can't select overlapping range");
      return;
    }
    range.addClass("reserved");
    $(".firstClick").addClass("checkin").removeClass("firstClick");
    $(this).addClass("checkout");
  }
});
table {
  border-collapse: collapse;
}

table tr td {
  width: 14%;
}

table tr td:hover {
  cursor: pointer;
}

.firstClick {
  background: green;
}

.checkin {
  background: yellow;
}

.checkout {
  background: red;
}

.reserved {
  background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
  <tr>
    <td colspan="7"><b>2016</b>
    </td>
  </tr>
  <tr>
    <td colspan="7"><i>November</i>
    </td>
  </tr>
  <tr>
    <th>mon</th>
    <th>tue</th>
    <th>wed</th>
    <th>thu</th>
    <th>fri</th>
    <th>sat</th>
    <th>sun</th>
  </tr>
  <tr>
    <td></td>
    <td class="day">1</td>
    <td class="day">2</td>
    <td class="day">3</td>
    <td class="day">4</td>
    <td class="day">5</td>
    <td class="day">6</td>
  </tr>
  <tr>
    <td class="day">7</td>
    <td class="day">8</td>
    <td class="day">9</td>
    <td class="day">10</td>
    <td class="day">11</td>
    <td class="day">12</td>
    <td class="day">13</td>
  </tr>
  <tr>
    <td class="day">14</td>
    <td class="day">15</td>
    <td class="day">16</td>
    <td class="day">17</td>
    <td class="day">18</td>
    <td class="day">19</td>
    <td class="day">20</td>
  </tr>
  <tr>
    <td class="day">21</td>
    <td class="day">22</td>
    <td class="day">23</td>
    <td class="day">24</td>
    <td class="day">25</td>
    <td class="day">26</td>
    <td class="day">27</td>
  </tr>
  <tr>
    <td class="day">28</td>
    <td class="day">29</td>
    <td class="day">30</td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</table>

Sign up to request clarification or add additional context in comments.

9 Comments

Hello and thank you Barmar! I will test it. Can you also tell me how I can prevent the second click on a day before the first day is executed?
if (firstClickIndex > currentIndex) will detect this case.
Yes, thank you very much. Already found it :-)
Hello again, I noticed that an overlap is possible for tag 2. But this one has the correct class "reserved". Do you have any idea?
What do you mean by tag 2? Do you mean the checkout date? It has class="checkout" but not class="reserved"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.