用 JavaScript 编写日历

概述

在本教程中,我将介绍使用几行 JavaScript 将日历渲染到网页上。日历将包括仅使用普通旧 JavaScript的月份和年份的下拉列表。流程如下:

  • 将月份渲染到下拉列表中
  • 将年份渲染到下拉列表中
  • 呈现当前选择的月/年组合的天数
  • 更改月份/年份时重新绘制日历

更改月份和/或年份将重新绘制日历以匹配给定月份和年份的正确日期。

如果你是 JavaScript 的初学者,或者只是需要更多的洞察力,我强烈推荐你可以在亚马逊上购买的 JavaScript Ninja 的秘密。这是一本扎实的读物,本书对 JavaScript 的许多微妙方面进行了非常深入的探讨,供那些刚接触 JavaScript 的人使用。

最终渲染的日历将如下所示。

的HTML

日历由一个父 div组成, 其中包含 3 个主要组件。前两个组件是月份的下拉列表,另一个是给定年份范围的下拉列表。

而且由于一周中的日子不太可能很快改变,我继续手动创建日历日标题。当页面加载时,脚本将从浏览器中获取当前用户的月份和年份,并根据当前日期/时间绘制日历。

HTML

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            body, *{
                padding:0px;
                margin:0px;
                box-sizing: border-box;
            }
            .calendar
            {
                background-color: white;
                padding: 20px;
                box-shadow: 0px 5px 10px rgba(0,0,0,0.4);
            }

            .calendar .dropdown
            {
                display: none;
                position: absolute;
                background-color: #fff;
                color: #1caff6;
                text-align: center;
                font-size: 14pt;
                padding-top: 5px;
                padding-bottom: 5px;
                padding-left: 30px;
                padding-right: 30px;
                width: 160px;
                left: 0px;
                z-index: 2000;
            }

            .calendar .dropdown .dropdown-item
            {
                cursor:pointer;
                opacity: .7;
                transition: .5s opacity;
            }

            .calendar .dropdown .dropdown-item:hover
            {
                opacity: 1;
            }

            .calendar .years
            {
                display:none;
            }

            .calendar .title
            {
                text-align:center;
                font-size:20pt;
            }

            .calendar .calendar-btn
            {
                float: left;
                background-color: #24aeff;
                color: white;
                text-align: center;
                font-size: 14pt;
                padding-top: 5px;
                padding-bottom: 5px;
                position: relative;
                width: 20%;
                cursor: pointer;
                transition: .5s background-color;
            }

            .calendar .calendar-btn:hover{
                background-color:#1f71a1;
            }

            .calendar .year-btn
            {
                float:right;
            }

            .calendar .calendar-dates .days .day
            {
                float:left;
                width: 12%;
                margin: 1%;
                padding: 1%;
                font-size:13pt;
                text-align:center;
                border-radius: 10px;
                border: solid 1px #ddd;
            }

            .calendar .calendar-dates .days .day.blank
            {
                background-color: white;
                border:none;
            }

            .calendar .calendar-dates .days .day.selected
            {
                background-color: #1caff6;
                color: white;
                cursor:pointer;
                opacity: .5;
                transition: .5s opacity;
            }

            .calendar .calendar-dates .days .day.selected:hover
            {
                opacity: 1;
            }

            .calendar .calendar-dates .days .day.label
            {
                height: 40px;
                background-color: white;
                color: black;
                border:none;
                font-weight:bold;
            }

            .clear{
                clear:both;
            }

            @media only screen and (max-width: 960px) {
                .calendar{
                    width: 100%;
                    margin: 0px;
                    margin: 0px;
                    box-sizing: border-box;
                    position: relative;
                    left: 0px;
                }
            }
        </style>
    </head>
    <body>
        <div class="calendar" id="calendar">
            <div class="calendar-btn month-btn" onclick="toggleMonths()">
                <span id="curMonth"></span>
                <div id="months" class="months dropdown"></div>
            </div>

            <div class="calendar-btn year-btn" onclick="toggleYears()">
                <span id="curYear"></span>
                <div id="years" class="years dropdown"></div>
            </div>

            <div class="clear"></div>

            <div class="calendar-dates">
                <div class="days">

                    <div class="day label">一</div>
                    <div class="day label">二</div>
                    <div class="day label">三</div>
                    <div class="day label">四</div>
                    <div class="day label">五</div>
                    <div class="day label">六</div>
                    <div class="day label">日</div>

                    <div class="clear"></div>
                </div>

                <div id="calendarDays" class="days">
                </div>
            </div>
        </div>
        <script>

            function toggleMonths() {
                var cont = document.getElementById('months');
                if (cont.style.display == 'block') {
                    cont.style.display = 'none';

                } else {
                    cont.style.display = 'block';
                }
            }
            function toggleYears() {
                var cont = document.getElementById('years');
                if (cont.style.display == 'block') {
                    cont.style.display = 'none';

                } else {
                    cont.style.display = 'block';
                }
            }

            var months = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"];
            const curDate = new Date();
            const curYear = curDate.getFullYear(); // returns 95
            console.log(curYear);
            var startYear = curYear - 20;
            var endYear = curYear + 20;
            var month = 0;
            var year = 0;

            function loadCalendarMonths() {
                for (var i = 0; i < months.length; i++) {
                    var doc = document.createElement("div");
                    doc.innerHTML = months[i];
                    doc.classList.add("dropdown-item");

                    doc.onclick = (function () {
                        var selectedMonth = i;
                        return function () {
                            month = selectedMonth;
                            document.getElementById("curMonth").innerHTML = months[month];
                            loadCalendarDays();
                            return month;
                        }
                    })();

                    document.getElementById("months").appendChild(doc);
                }
            }

            function loadCalendarYears() {
                document.getElementById("years").innerHTML = "";

                for (var i = startYear; i <= endYear; i++) {
                    var doc = document.createElement("div");
                    doc.innerHTML = i;
                    doc.classList.add("dropdown-item");

                    doc.onclick = (function () {
                        var selectedYear = i;
                        return function () {
                            year = selectedYear;
                            document.getElementById("curYear").innerHTML = year;
                            loadCalendarDays();
                            return year;
                        }
                    })();

                    document.getElementById("years").appendChild(doc);
                }
            }

            function ISO_numeric_date(dt)
            {
                return (dt.getDay() === 0 ? 7 : dt.getDay());
            }

            function loadCalendarDays() {
                document.getElementById("calendarDays").innerHTML = "";

                var tmpDate = new Date(year, month, 0);
                var num = daysInMonth(month, year);
                var dayofweek = ISO_numeric_date(tmpDate);       // find where to start calendar day of week

                for (var i = 1; i <= dayofweek; i++) {
                    var d = document.createElement("div");
                    d.classList.add("day");
                    d.classList.add("blank");
                    document.getElementById("calendarDays").appendChild(d);
                }

                for (var i = 0; i < num; i++) {
                    var tmp = i + 1;
                    var d = document.createElement("div");
                    d.id = "calendarday_" + i;
                    d.className = "day";
                    d.innerHTML = tmp;

                    document.getElementById("calendarDays").appendChild(d);
                }

                var clear = document.createElement("div");
                clear.className = "clear";
                document.getElementById("calendarDays").appendChild(clear);
            }

            function daysInMonth(month, year)
            {
                var d = new Date(year, month + 1, 0);
                return d.getDate();
            }

            window.addEventListener('load', function () {
                var date = new Date();
                month = date.getMonth();
                year = date.getFullYear();
                document.getElementById("curMonth").innerHTML = months[month];
                document.getElementById("curYear").innerHTML = year;
                loadCalendarMonths();
                loadCalendarYears();
                loadCalendarDays();
            }
            );

        </script>
    </body>
</html>

创建月份

幸运的是,一年只有 12 个月,我们可以将它们存储为一个简单的字符串数组。该数组将用于在  id 为“months”的div中创建下拉列表。

<script>
    var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

    function drawCalendarMonths()
    {
        for(var i = 0; i < months.length; i++)
        {
            var doc = document.createElement("div");
            doc.innerHTML = months[i];
            doc.classList.add("dropdown-item");

            doc.onclick = (function () {
                var selectedMonth = i;
                return function ()
                {
                    month = selectedMonth;
                    document.getElementById("curMonth").innerHTML = months[month];
                    loadCalendarDays();
                    return month;
                }
            })();

            document.getElementById("months").appendChild(doc);
        }
    }
</script>

运行该函数,结果应该如下:

记下我们选择新月份时调用的loadCalendarDays()函数。This function will redraw the calendar whenever a new month is selected to reflect the new month selection.

创建年份

我们可以按照类似的过程来呈现年份下拉列表。


    function loadYears()
    {
        // whichever date range makes the most sense
        var startYear = 1900;
        var endYear = 2022;

        for(var i = startYear; i <= endYear; i++)
        {
            var doc = document.createElement("div");
            doc.innerHTML = i;
            doc.classList.add("dropdown-item");

            doc.onclick = (function(){
                var selectedYear = i;
                return function(){
                    year = selectedYear;
                    document.getElementById("curYear").innerHTML = year;
                    loadCalendarDays();
                    return year;
                }
            })();

            document.getElementById("years").appendChild(doc);
        }
    }

请注意,我从 1900 年开始年份下拉列表,并在 2022 年结束它。您当然可以更新这些变量以满足您自己的需要。

该过程与渲染月份基本相同。如果选择了任何年份,将调用loadCalendarDays () 函数以重新呈现日历日。

创造日

现在我们处于日历的核心。日渲染有点类似于之前的月份和年份生成函数。我们实际上是要计算指定年/月期间的天数,然后为计算的每一天创建一个div >

另请注意,只要日历需要重绘,例如当我们从任一下拉列表中选择新月份或新年份时,就会调用此函数。

daysInMonth():我创建了一个名为 daysInMonth()的辅助函数,它将返回所选月/年期间的天数。我们基本上会遍历这些天,并在我们的日历上为找到的每个元素创建一个“天”元素。

getDay():JavaScript Date 对象为我们提供了getDay()方法,该方法将返回任何给定日期的星期几。在我们的例子中,我们想知道这个月的第一天是什么时候。我们将通过创建没有特定含义的空“day”元素来忽略前几天留下的内容。


    function daysInMonth(month, year)
    {
        let d = new Date(year, month+1, 0);
        return d.getDate();
    }

    function loadCalendarDays()
    {
        document.getElementById("calendarDays").innerHTML = "";

        var tmpDate = new Date(year, month, 0);
        var num = daysInMonth(month, year);
        var dayofweek = tmpDate.getDay();       // find where to start calendar day of week

在这里,我正在清理“画布”,并计算当月的总天数和我们将在一周中的哪一天开始这个月。


        // create day prefixes
        for(var i = 0; i <= dayofweek; i++)
        {
            var d = document.createElement("div");
            d.classList.add("day");
            d.classList.add("blank");
            document.getElementById("calendarDays").appendChild(d);
        }

我们希望忽略日历第一天之前的任何日子。上面的循环本质上会在日历中添加空的日期元素。下面的函数会将实际的日历日渲染到主 div 容器上。


        // render the rest of the days
        for(var i = 0; i < num; i++)
        {
            var tmp = i + 1;
            var d = document.createElement("div");
            d.id = "calendarday_" + i;
            d.className = "day";
            d.innerHTML = tmp;
            document.getElementById("calendarDays").appendChild(d);
        }

        var clear = document.createElement("div");
        clear.className = "clear";
        document.getElementById("calendarDays").appendChild(clear);
    }

在第 2 部分

此时,您应该有一个可以显示任何给定月份和年份组合的日期的日历。在第 2 部分中,我将介绍每天的单个日期选择、日期范围选择和自定义事件。同时,请随意下载下面的资源文件并更新、修改、改进和享受代码。

更新:第 2 部分可以 在这里找到。

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值