You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在jQuery实现的HTML日历中防止多选日期范围重叠?

多日期范围选择日历的逻辑实现与防重叠方案

需求逻辑:

  • 第一次点击选择起始日
  • 第二次点击选择结束日(必须晚于起始日)
  • 第三次点击选择下一个起始日
  • 第四次点击选择下一个结束日

希望通过index()方法实现,同时要防止时间范围重叠,以下是当前实现代码:

现有代码

HTML

<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>

CSS

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;
}

JavaScript

$("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");
    }
});

改进方案(基于index()实现多范围选择与防重叠)

当前代码仅支持单范围选择,要实现多范围并防重叠,需调整状态判断和重叠校验逻辑:

  1. 状态追踪:用变量记录当前是否在选择起始日,区分多范围下的选择阶段
  2. 重叠校验:通过index()判断当前日期是否已被占用,或新范围是否与已有范围重叠
  3. 边界处理:确保结束日晚于起始日,避免无效选择

修改后的JavaScript代码:

// 标记当前是否处于选择起始日的状态
let isSelectingStart = false;
// 存储所有已选日期范围
const selectedRanges = [];

$("td.day").click(function() {
    const $day = $(this);
    const tds = $("td.day");
    const currentIndex = tds.index($day);

    // 跳过已被占用的日期
    if ($day.hasClass('reserved') || $day.hasClass('checkin') || $day.hasClass('checkout')) {
        return;
    }

    if (!isSelectingStart) {
        // 选择新的起始日
        $day.addClass('firstClick');
        isSelectingStart = true;
    } else {
        const $startDay = $('.firstClick');
        const startIndex = tds.index($startDay);

        // 确保结束日晚于起始日
        if (currentIndex <= startIndex) {
            alert('结束日期必须晚于起始日期');
            return;
        }

        // 检查新范围是否与已有范围重叠
        let isOverlap = false;
        selectedRanges.forEach(range => {
            if ((startIndex > range.startIndex && startIndex < range.endIndex) || 
                (currentIndex > range.startIndex && currentIndex < range.endIndex) ||
                (startIndex < range.startIndex && currentIndex > range.endIndex)) {
                isOverlap = true;
            }
        });

        if (isOverlap) {
            alert('该日期范围与已选范围重叠,请重新选择');
            $startDay.removeClass('firstClick');
            isSelectingStart = false;
            return;
        }

        // 标记日期范围
        $startDay.removeClass('firstClick').addClass('checkin');
        $day.addClass('checkout');
        tds.filter(function() {
            const idx = tds.index(this);
            return idx > startIndex && idx < currentIndex;
        }).addClass('reserved');

        // 保存新范围
        selectedRanges.push({
            startIndex: startIndex,
            endIndex: currentIndex
        });

        isSelectingStart = false;
    }
});

逻辑说明:

  • 状态管理:通过isSelectingStart变量控制选择阶段,解决多范围选择的流程判断问题
  • 重叠校验:遍历已选范围,利用日期的index值交叉对比,确保新范围不与任何已有范围重叠
  • 无效拦截:禁止选择早于起始日的结束日,同时跳过已被标记的日期,避免重复操作

内容的提问来源于stack exchange,提问作者user3270967

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:37:05