RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1534356
Accepted
powerg
powerg
Asked:2023-08-05 19:08:57 +0000 UTC2023-08-05 19:08:57 +0000 UTC 2023-08-05 19:08:57 +0000 UTC

如何检测点击时的元素?

  • 772

您能告诉我如何确定点击时的元素吗?如果您点击周五/周六/周日的任何一天,该课程将仅在第二次点击时添加到页面中。谢谢

const calendar = document.querySelector(".calendar__main");
if (calendar) {
    const input = document.querySelector("#date");
    const calHeader = document.querySelector(".calendar__header");
    const calHeaderTitle = document.querySelector(".calendar__header span");
    const calDays = document.querySelector(".calendar__days");
    const days = [
        "Пн",
        "Вт",
        "Ср",
        "Чт",
        "Пт",
        "Сб",
        "Вс"
    ];
    const months = [
        "Январь",
        "Февраль",
        "Март",
        "Апрель",
        "Май",
        "Июнь",
        "Июль",
        "Август",
        "Сентябрь",
        "Октябрь",
        "Ноябрь",
        "Декабрь"
    ];

    let oneDay = 60 * 60 * 24 * 1000;
    let todayTimestamp =
        Date.now() -
        (Date.now() % oneDay) +
        new Date().getTimezoneOffset() * 1000 * 60;

    let selectedDay = todayTimestamp;
    // console.log(selectedDay); // Str in millisec

    // Get num of days in month
    // month param 0-11
    const getNumberOfDays = (year, month) => {
        return 40 - new Date(year, month, 40).getDate();
    };
    // getNumberOfDays(2023, 1);

    // Calc day details
    const getDayDetails = (args) => {
        let date = args.index - args.firstDay;
        let day = args.index % 7;
        // console.log(day)
        let prevMonth = args.month - 1;
        let prevYear = args.year;
        if (prevMonth < 0) {
            prevMonth = 11;
            prevYear--;
        }
        let prevMonthNumberOfDays = getNumberOfDays(prevYear, prevMonth);

        let _date =
            (date < 0 ? prevMonthNumberOfDays + date : date % args.numberOfDays) + 1;
        // console.log(_date)
        let month = date < 0 ? -1 : date >= args.numberOfDays ? 1 : 0;
        let timestamp = new Date(args.year, args.month, _date).getTime();
        // console.log(timestamp)
        return {
            date: _date,
            day,
            month,
            timestamp,
            dayString: days[day]
        };
    };

    // [{}] each {} with details for each day of month
    const getMonthDetails = (year, month) => {
        let firstDay = new Date(year, month).getDay();
        let numberOfDays = getNumberOfDays(year, month);
        let monthArray = [];
        let rows = 5;
        let currentDay = null;
        let index = 0;
        let cols = 7;

        for (let row = 0; row < rows; row++) {
            for (let col = 0; col < cols; col++) {
                currentDay = getDayDetails({
                    index,
                    numberOfDays,
                    firstDay,
                    year,
                    month
                });
                monthArray.push(currentDay);
                index++;
            }
        }
        return monthArray;
    };
    // getMonthDetails(2023, 3)

    // Variables that get updated with "state" changes
    let date = new Date();
    let year = date.getFullYear();
    let month = date.getMonth();
    let monthDetails = getMonthDetails(year, month);

    const isCurrentDay = (day, cell) => {
        if (day.timestamp === todayTimestamp) {

            cell.classList.add("active");
            cell.classList.add("isCurrent");

        }
    };

    // Checks if day is one selected
    const isSelectedDay = (day, cell) => {
        if (day.timestamp === selectedDay) {
            cell.classList.add("active");
            cell.classList.add("isSelected");
        }
    };

    // Get month str
    const getMonthStr = (month) =>
        months[Math.max(Math.min(11, month), 0)] || "Month";
    // console.log(getMonthStr(month))

    // Set year using arrows
    const setHeaderNav = (offset) => {
        month = month + offset;
        if (month === -1) {
            month = 11;
            year--;
        } else if (month === 12) {
            month = 0;
            year++;
        }
        monthDetails = getMonthDetails(year, month);
        // console.log(getMonthDetails(year, month))
        return {
            year,
            month,
            monthDetails
        };
    };

    // Set dynamic calendar header
    const setHeader = (year, month) => {
        calHeaderTitle.innerHTML = getMonthStr(month) + " " + year;
    };

    // Set calendar header
    setHeader(year, month);

    // 1677139200000 => "2023-02-23"
    const getDateStringFromTimestamp = (timestamp) => {
        let dateObject = new Date(timestamp);
        let month = dateObject.getMonth();
        let date = dateObject.getDate();
        // return (
        //   dateObject.getFullYear() +
        //   "-" +
        //   (month < 10 ? "0" + month : month) +
        //   "-" +
        //   (date < 10 ? "0" + date : date)
        // );
        return `${getMonthStr(month)} ${date}, ${dateObject.getFullYear()}`;
    };

    const setDateToInput = (timestamp) => {
        let dateString = getDateStringFromTimestamp(timestamp);
        input.value = dateString;
    };
    setDateToInput(todayTimestamp);

    // Add days row to calendar
    for (let i = 0; i < days.length; i++) {
        let div = document.createElement("div"),
            span = document.createElement("span");

        div.classList.add("cell_wrapper");
        // div.classList.add("cal_days");
        span.classList.add("cell_item");

        span.innerText = days[i].slice(0, 2);

        div.appendChild(span);
        calDays.appendChild(div);
    }

    // Add dates to calendar
    const setCalBody = (monthDetails) => {
        // Add dates to calendar
        for (let i = 0; i < monthDetails.length; i++) {
            let div = document.createElement("div"),
                span = document.createElement("span");

            div.classList.add("cell_wrapper");
            div.classList.add("cal_date");
            monthDetails[i].month === 0 && div.classList.add("current");
            monthDetails[i].month === 0 && isCurrentDay(monthDetails[i], div);
            span.classList.add("cell_item");
            var fifth_1 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(5)")
            fifth_1.forEach(five => {
                five.classList.add("fifth-day");
            });
            var fifth_2 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(12)")
            fifth_2.forEach(five => {
                five.classList.add("fifth-day");
            });
            var fifth_3 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(19)")
            fifth_3.forEach(five => {
                five.classList.add("fifth-day");
            });
            var fifth_4 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(26)")
            fifth_4.forEach(five => {
                five.classList.add("fifth-day");
            });
            var fifth_5 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(33)")
            fifth_5.forEach(five => {
                five.classList.add("fifth-day");
            });

            var sixth_1 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(6)")
            sixth_1.forEach(six => {
                six.classList.add("sixth-day");
            });
            var sixth_2 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(13)")
            sixth_2.forEach(six => {
                six.classList.add("sixth-day");
            });
            var sixth_3 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(20)")
            sixth_3.forEach(six => {
                six.classList.add("sixth-day");
            });
            var sixth_4 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(27)")
            sixth_4.forEach(six => {
                six.classList.add("sixth-day");
            });
            var sixth_5 = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(34)")
            sixth_5.forEach(six => {
                six.classList.add("sixth-day");
            });

            var seventh = document.querySelectorAll(".calendar__main .cell_wrapper.cal_date:nth-child(7n)")
            seventh.forEach(seven => {
                seven.classList.add("seventh-day");
            });

            span.innerText = monthDetails[i].date;

            div.appendChild(span);
            calendar.appendChild(div);
        }
    };

    setCalBody(monthDetails);

    const updateCalendar = (btn) => {
        let newCal, offset;
        if (btn.classList.contains("calendar__btn-prev")) {
            // let { year, month, monthDetails } = setHeaderNav(-1);
            offset = -1;
        } else if (btn.classList.contains("calendar__btn-next")) {
            // let { year, month, monthDetails } = setHeaderNav(1);
            offset = 1;
        }
        newCal = setHeaderNav(offset);
        // console.log(monthDetails)
        setHeader(newCal.year, newCal.month);
        calendar.innerHTML = "";
        setCalBody(newCal.monthDetails);
    };

    // Only one calendar date is selected
    const selectOnClick = () => {
        document.querySelectorAll(".cell_wrapper").forEach((cell) => {
            cell.classList.contains("isSelected") && cell.classList.remove("active");
            if (cell) {
                cell.addEventListener("click", function (e) {
                    const calendarItemFifth = document.querySelector('.cell_wrapper.cal_date.current.fifth-day.active');
                    console.log(calendarItemFifth)
                    if (calendarItemFifth) {
                        document.documentElement.classList.add("_active-wek-fifth")
                    } else {
                        document.documentElement.classList.remove("_active-wek-fifth")
                    }
                    const calendarItemsSixth = document.querySelector('.cell_wrapper.cal_date.current.sixth-day.active.isSelected');
                    console.log(calendarItemsSixth)
                    if (calendarItemsSixth) {
                        document.documentElement.classList.add("_active-wek-sixth")
                    } else {
                        document.documentElement.classList.remove("_active-wek-sixth")
                    }
                    const calendarItemSeventh = document.querySelector('.cell_wrapper.cal_date.current.seventh-day.active.isSelected');
                    console.log(calendarItemSeventh)
                    if (calendarItemSeventh) {
                        document.documentElement.classList.add("_active-wek-seventh")
                    } else {
                        document.documentElement.classList.remove("_active-wek-seventh")
                    }
                });

            }
            if (cell.classList.contains("isCurrent") &&
                !cell.classList.contains("active")) {
                cell.querySelector("span").classList.add("inactive_indicator");
            }
        });
    };


    const updateInput = () => {
        let currentDay = document.querySelector(".isCurrent");

        // Update input based on clicked cell
        document.querySelectorAll(".cell_wrapper").forEach((cell) => {
            if (cell.classList.contains("current")) {
                cell.addEventListener("click", (e) => {
                    let cell_date = e.target.textContent;

                    currentDay !== null && currentDay.classList.remove("active");

                    for (let i = 0; i < monthDetails.length; i++) {
                        if (monthDetails[i].month === 0) {
                            if (monthDetails[i].date.toString() === cell_date) {
                                selectedDay = monthDetails[i].timestamp;
                                setDateToInput(selectedDay);
                                selectOnClick();

                                isSelectedDay(monthDetails[i], cell);

                                cell.querySelector('span').classList.contains('inactive_indicator')
                                    && cell.querySelector('span').classList.remove('inactive_indicator');
                            }
                        }
                    }
                });
            }
        });
    };

    updateInput();

    // Set header nav actions
    document.querySelectorAll(".calendar-btn").forEach((btn) => {
        btn.addEventListener("click", () => {
            updateCalendar(btn);
            updateInput();
        });
    });

    input.addEventListener('click', () => {
        document.querySelector('.calendar__content').classList.toggle('hidden');
        document.querySelector('.calendar__input').classList.toggle('showCal');
        document.querySelector('#date').classList.toggle('onFocus');
    });
    window.addEventListener('click', e => {
        const target = e.target
        if (!target.closest('#date') && !target.closest('.calendar__input') && !target.closest('.calendar__content')) {
            document.querySelector('.calendar__content').classList.add('hidden');
            document.querySelector('.calendar__input').classList.remove('showCal');
            document.querySelector('#date').classList.add('onFocus');
        }
    })

}
.calendar{
  position: relative;
}
.calendar__input {
  position: relative;
  cursor: pointer;
  width: 100%;
}
.calendar__input input {
  cursor: pointer;
   width: 100%;
}
.calendar__input input._form-focus {
  border: 1px solid #ebebeb;
}
.calendar__input.showCal input {
  border: 1px solid green;
}
.calendar__input.showCal::before {
  color: green;
}
.calendar__input::before {
  position: absolute;
  right: 20px;
  font-size: 20px;
  color: #afafaf;
  top: 50%;
  transform: translate(0, -50%);
  pointer-events: none;
}
.calendar__content {
  position: absolute;
  z-index: 40;
  right: 0;
  padding: 25px;
  top: 99%;
  width: auto;
  background: #f8f8f8;
  border: 1px solid green;
  border-radius: 2px;
}
.calendar__header {
  display: flex;
  align-items: center;
  font-weight: 400;
  font-size: 16px;
  margin: 0px 0px 24px 0px;
}
.calendar__header span {
  flex: 1 1 auto;
}
.calendar__btn-prev {
  width: 24px;
  height: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0px 27px 0px 0px;
}
.calendar__btn-prev::before {
  font-size: 16px;
  transform: rotate(-90deg);
}
.calendar__btn-prev:hover::before {
  color: green;
}
.calendar__btn-next {
  width: 24px;
  height: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.calendar__btn-next::before {
  font-size: 16px;
  transform: rotate(90deg);
}
.calendar__btn-next:hover::before {
  color: green;
}
.calendar__days {
  display: grid;
  column-gap: 35px;
  grid-template-columns: repeat(7, 1fr);
  margin: 0px 0px 16px 0px;
}
.calendar__main {
  display: grid;
  column-gap: 35px;
  row-gap: 16px;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: repeat(5, min(32px));
}

.cal_date .cell_item {
  cursor: pointer;
  min-width: 32px;
  min-height: 32px;
}

.cell_wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}
.cell_wrapper .cell_item {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 32px;
  position: relative;
  font-weight: 400;
  font-size: 16px;
  border-radius: 50%;
  color: rgba(49, 49, 49, 0.5);
}
.cell_wrapper.active .cell_item {
  background: #efa021;
  color: #ffffff;
}

.current .cell_item {
  color: #111111;
}

.hidden {
  visibility: hidden;
}
<div class="tabs-transmit-readings__calendar calendar">
  <div class="calendar__input  _icon-calendar">
    <input autocomplete="off" type="text" id="date" class="onFocus" readonly>
  </div>
  <div class="calendar__content hidden">
    <div class="calendar__header">
      <span></span>
      <button class="calendar__btn-prev calendar-btn _icon-arrow-slider"></button>
      <button class="calendar__btn-next calendar-btn _icon-arrow-slider"></button>
    </div>
    <div class="calendar__wrapper">
      <div class="calendar__days"></div>
      <div class="calendar__main"></div>
    </div>
  </div>
</div>

javascript
  • 1 1 个回答
  • 41 Views

1 个回答

  • Voted
  1. Best Answer
    Daniil Loban
    2023-08-06T02:13:58Z2023-08-06T02:13:58Z

    当然,一般来说,我会完全重写您的代码中的很多内容,因为对我来说其中存在冗余,因此难以理解/控制其工作。

    理解任务的复杂性和理解代码的复杂性是不同的事情,第二个完全不应该有问题,因为第二个复杂性是程序员自己创造的:)

    Помимо дублирования кода, неоднозначности имен таких как selected, active, isCurrent и т.п. есть еще опасная практика навешивания событий — по сути и создание календаря и навешивание событий достаточно произвести 1 раз более того использовав делегирование. Очень многое можно получить путем простых вычислений или через переменные. Большая вложенность кода, тоже настораживает, условия, циклы в циклах (forEach, for) и т.п.

    Но если подходить не так радикально то вот 2 функции которые я подправил, после чего код работает как ожидается, код снабжен комментариями для лучшего понимания:

    // эта функция переписана координально, что позволило убрать из нее цикл
    // а так же ряд дублирований, в целом можно написать код еще проще
    // но это затронет и остальные уже написанные функции.
    const selectOnClick = (cell) => {  // добавлен параметр чтобы избежать цикла
        const target = cell.closest('.cell_wrapper') // находим ближайший таргет
        const cond = target.classList.contains('active'); 
        let action = 'add/remove' // чтобы не писать if-else
        Object.entries({ // объект соответсвий может быть объявлен в другом месте
            'fifth-day': '_active-wek-fifth',
            'sixth-day': '_active-wek-sixth',
            'seventh-day': '_active-wek-seventh'
        }).forEach(([k, v]) => { // ключ и значение из таблицы соответсвий
            const test = cond && target.classList.contains(k);
            const action = test ? 'add' : 'remove'
            document.documentElement.classList[action](v)
        })
        if (cell.classList.contains("isCurrent") &&
            !cell.classList.contains("active")) {
            cell.querySelector("span").classList.add("inactive_indicator");
        }
    };
    
    // эта функция притерпела минимум изменений: добавлена одна строка
    // и две строки поменялись местами, в вызов функции добавлен аргумент.
    const updateInput = () => {
        let currentDay = document.querySelector(".isCurrent");
        // Update input based on clicked cell
        document.querySelectorAll(".cell_wrapper").forEach((cell) => {
            if (cell.classList.contains("current")) {
                cell.addEventListener("click", (e) => {
                    // добавлена очистка предыдущего выделенного дня
                    document.querySelector(".active")?.classList.remove("active");
                    let cell_date = e.target.textContent;
                    for (let i = 0; i < monthDetails.length; i++) {
                        if (monthDetails[i].month === 0) {
                            if (monthDetails[i].date.toString() === cell_date) {
                                selectedDay = monthDetails[i].timestamp;
                                setDateToInput(selectedDay);
                                isSelectedDay(monthDetails[i], cell); // вызов перед selectOnClick
                                // вообще в isSelectedDay сетить классы не очень хорошая идея
                                // функции is многими программистами воспринимаются как чистые
                                // т.е. функции которые ничего не меняют
                                selectOnClick(cell); // добавлен аргумент
                                cell.querySelector('span').classList.contains('inactive_indicator')
                                    && cell.querySelector('span').classList.remove('inactive_indicator');
                            }
                        }
                    }
                });
            }
        });
    };
    
    • 0

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5