对于循环在预订网站中不起作用,日期不是连续的

For loop not working in booking site, the dates are not serial

提问人:Harshvardhan Sinha 提问时间:8/12/2023 最后编辑:Don't PanicHarshvardhan Sinha 更新时间:8/13/2023 访问量:33

问:

我正在尝试制作一个预订网站,然后出现了一个问题,即 for 循环正在工作或我的逻辑错误。

我期待(旧版本代码的屏幕截图):

输出是什么(新版本的屏幕截图):

此外,我正在为此使用 PHP,并且正在按预期工作。当我尝试发出 AJAX 请求时,可能出了点问题。check_date.php

// JavaScript code for generating the calendar and handling month navigation
const calendarContainer = document.getElementById("calendar");
const prevMonthBtn = document.getElementById("prevMonth");
const nextMonthBtn = document.getElementById("nextMonth");
const currentMonthYear = document.getElementById("currentMonthYear");

const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const months = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"
];

const currentDate = new Date();
let currentMonth = currentDate.getMonth();
let currentYear = currentDate.getFullYear();

function generateCalendar() {
  const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
  const firstDayIndex = new Date(currentYear, currentMonth, 1).getDay();

  calendarContainer.innerHTML = "";

  // Display days of the week at the top of the calendar
  for (const dayOfWeek of daysOfWeek) {
    const dayOfWeekDiv = document.createElement("div");
    dayOfWeekDiv.classList.add("day");
    dayOfWeekDiv.textContent = dayOfWeek;
    calendarContainer.appendChild(dayOfWeekDiv);
  }

  for (let i = 0; i < firstDayIndex; i++) {
    const dayDiv = document.createElement("div");
    dayDiv.classList.add("day");
    calendarContainer.appendChild(dayDiv);
  }

  for (let i = 1; i <= daysInMonth; i++) {
    const dayDiv = document.createElement("a");
    dayDiv.href = "entry.php";
    let __ryear = currentYear.toString();
    let __rmonth = currentMonth.toString();
    let daI = i.toString();
    let result1 = __ryear.concat(__rmonth);
    let result2 = result1.concat(daI);
    // let ruiue = result2;
    // let date6969 = i;

    // AJAX request to check if the date exists in the database
    let xhr = new XMLHttpRequest();
    xhr.open("GET", "http://localhost/irctclogin/check_date.php?date=" + result2, true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4 && xhr.status == 200) {
        let response = xhr.responseText;
        if (response == "exists") {

          // Date exists in the database, continue the program
          let bookStatus = "booked";
          dayDiv.classList.add("day", result2, bookStatus);
          dayDiv.textContent = i;
          calendarContainer.appendChild(dayDiv);
          // dayDiv.value = i;

        }
          else {
            let bookStatus = "available";
            dayDiv.classList.add("day", result2, bookStatus);
            dayDiv.textContent = i;
            calendarContainer.appendChild(dayDiv);
            // dayDiv.value = i;
            // console.log(i);
          }
        }
      }
      xhr.send();
    }

    currentMonthYear.textContent = `${months[currentMonth]} ${currentYear}`;
    // console.log(`${months[currentMonth]} ${currentYear}`);
  }

  prevMonthBtn.addEventListener("click", () => {
    if (currentMonth === 0) {
      currentMonth = 11;
      currentYear--;
    } else {
      currentMonth--;
    }
    generateCalendar();
  });

  nextMonthBtn.addEventListener("click", () => {
    if (currentMonth === 11) {
      currentMonth = 0;
      currentYear++;
    } else {
      currentMonth++;
    }
    generateCalendar();
  });

  generateCalendar();

HTML 循环

评论


答:

0赞 Don't Panic 8/12/2023 #1

您的天数显示为乱序的原因是,它们是按照 AJAX 请求完成的顺序生成的。仅仅因为您按顺序触发了多个 AJAX 请求,并不意味着它们将按照您启动它们的顺序完成。因此,如果请求 #10 在请求 #9 之前完成,则每月 10 日的单元格将出现在第 9 个单元格之前。

这是一个工作片段,其中包含一些非常基本的 CSS,其中注释掉了 AJAX,这表明在没有 AJAX 的情况下生成日历可以正常工作。

const calendarContainer = document.getElementById("calendar");

const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const months     = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
];

const currentDate = new Date();
let currentMonth  = currentDate.getMonth();
let currentYear   = currentDate.getFullYear();

function generateCalendar() {
    const daysInMonth   = new Date(currentYear, currentMonth + 1, 0).getDate();
    const firstDayIndex = new Date(currentYear, currentMonth, 1).getDay();

    calendarContainer.innerHTML = "";

    // Display days of the week at the top of the calendar
    for (const dayOfWeek of daysOfWeek) {
        const dayOfWeekDiv = document.createElement("div");
        dayOfWeekDiv.classList.add("day");
        dayOfWeekDiv.textContent = dayOfWeek;
        calendarContainer.appendChild(dayOfWeekDiv);
    }

    for (let i = 0; i < firstDayIndex; i++) {
        const dayDiv = document.createElement("div");
        dayDiv.classList.add("day");
        calendarContainer.appendChild(dayDiv);
    }

    for (let i = 1; i <= daysInMonth; i++) {
        const dayDiv = document.createElement("a");
        dayDiv.href  = "entry.php";
        let __ryear  = currentYear.toString();
        let __rmonth = currentMonth.toString();
        let daI      = i.toString();
        let result1  = __ryear.concat(__rmonth);
        let result2  = result1.concat(daI);

        // AJAX request to check if the date exists in the database
        // let xhr = new XMLHttpRequest();
        // xhr.open("GET", "http://localhost/irctclogin/check_date.php?date=" + result2, true);
        // xhr.onreadystatechange = function() {
        //   if (xhr.readyState == 4 && xhr.status == 200) {
        //     let response = xhr.responseText;
        //     if (response == "exists") {
        //
        //       // Date exists in the database, continue the program
        //       let bookStatus = "booked";
        //       dayDiv.classList.add("day", result2, bookStatus);
        //       dayDiv.textContent = i;
        //       calendarContainer.appendChild(dayDiv);
        //       // dayDiv.value = i;
        //
        //     }
        //       else {
                let bookStatus = "available";
                dayDiv.classList.add("day", result2, bookStatus);
                dayDiv.textContent = i;
                calendarContainer.appendChild(dayDiv);
        //         // dayDiv.value = i;
        //         // console.log(i);
        //       }
        //     }
        //   }
        //   xhr.send();
    }
}

generateCalendar();
a {
    display: inline-block;
    width: 50px;
    border: 1px solid black;
}
<div id="calendar"></div>

一个更好的方法是独立于AJAX生成日历,例如在页面加载时,就像一个等待数据的空模板一样。您已经根据日期(在代码中)为每个单元格指定了一个唯一的类。因此,当您获得 2023 年 7 月 23 日的 AJAX 结果时,您可以使用如下选择器找到需要更新的单元格:result2

// Say your AJAX returns some data with a value like 'date"
let cell = document.getElementsByClassName(date);
cell.classList.add('booked');

但是,在当月的每一天都触发一个单独的 AJAX 请求是非常低效的 - 完成这个月需要很长时间,而且似乎很有可能某些请求无法完成或被拒绝。在几分之一秒内收到 31 个请求似乎是因看起来像机器人而被阻止的好方法。

一个更好的选择是让 AJAX 一次返回一整月的数据。显然,您必须更新您的 PHP,并以可以表示多天的格式返回数据,每天都有一个预订状态。例如:

// Your PHP code, inside some kind of loop here, iterating over days in the month ..

$month[] = [
    'date'  => $date,
    'state' => $state // 'booked' or whatever ...
];

// Loop finished, now return data as JSON

header('Content-type: application/json');
echo json_encode($month);

现在,您的 Javascript 可以通过 1 次 AJAX 调用来处理整个月。您只需要遍历 JSON 响应,并使用正确的状态更新每个单元格。