日历控件值班表 原生JavaScript

983 阅读5分钟

日历值班表(移动端),网上找了好多三方的控件, 页面样式,功能都不太满足条件! 索性自己写一个! 要求可以查看当月排班记录,可以切换月份,单击某天回调等。。。

效果图如下

avatar

可以确认的是一屏日历需要显示6个星期42天,(例如本月30天,上个月2天,下个月10天)。明白页面组成后,要计算出本月总天数,以及本月第一天是星期几,以及上个月最后一天日期!这里有两个地方需要说一下

  1. 计算总天数采用了一个小技巧 new Date(year, month + 1, 0).getDate();月份加1 ,天传入一个0.就是上个月的最后一天的日期也就是当月的总天数

  2. 上月的起始日期, 举例; 上个月总天数(31)- 本月第一天星期(3)+ 最后1天(31日)+ 本月第1天(1日) 最后为 passdays = prefays - weekday + 2

var date = new Date();
var year = date.getFullYear(); // 年份
var month = date.getMonth(); //月份
var firstday = new Date(year, month, 1); // 当月第一天
var weekday = firstday.getDay(); // 当月第一天是星期几
var days = new Date(year, month + 1, 0).getDate(); // 当月总天数

if (month == 0) {
    var premonth = 12;
    var preyear = year - 1;
} else {
    var premonth = month - 1;
    var preyear = year;
}
var prefays = new Date(preyear, premonth + 1, 0).getDate(); // 上个月总天数

var res = '';
var passdays;
if (weekday == 0) {
    weekday = 7;
}
passdays = prefays - weekday + 2// 上个月起始日期

渲染日历

// 上个月部分
for (var i = 0; i < weekday - 1; i++) {
    res += '<div><span class="pass">' + passdays + '</span></div>';
    passdays++;
}
// 当月部分
for (var j = 1; j <= days; j++) {
    if (j == today && year == _year && month == _month) {
        res += '<div data-date="' + j + '"><span  class="on select">' + j +
            '</span></div>';
    } else {
        res += '<div data-date="' + j + '"><span>' + j + '</span></div>';
    }
}
// 下个月部分
var nextdays = 42 - days - weekday + 1;
for (var i = 1; i <= nextdays; i++) {
    res += '<div><span class="pass">' + i + '</span></div>';
}

Demo:

    <!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport"
        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <title></title>
    <style>
        .sign-alert {
            background: #fff;
            border-radius: 4px;
            width: 90%;
            margin: 0 auto;
            min-height: 200px;
            /* margin-top: 40%; */
            position: relative;
            padding-bottom: 20px;
            font-size: 12px;
        }

        .sign-week {
            width: 100%;
            background-color: #0071c0;
            height: 26px;
            display: flex;
            justify-content: space-around;
            line-height: 26px;
            color: #fff;
        }

        .sign-date {
            display: flex;
            justify-content: space-around;
            flex-wrap: wrap;
        }

        .sign-date div {
            padding: 6px 0;
            width: 14.2%;
            text-align: center;
        }

        .sign-date span {
            text-align: center;
            color: #0071c0;
            height: 20px;
            width: 20px;
            display: inline-block;
            line-height: 20px;
        }

        .sign-date p {
            margin: 0 auto;
            padding: 0;
            font-size: 20px;
            transform: scale(0.4);
            position: relative;
            margin-top: -12px;
            width: 20px;
        }

        .sign-date p::before {
            content: "";
            width: 10px;
            height: 10px;
            position: absolute;
            background-color: orange;
            border-radius: 10px;
            top: 24px;
            left: 5px;
        }

        .sign-date span.pass {
            color: #999999;
        }

        .sign-date span.on {
            border-radius: 50%;
            border: 1px solid #0071c0;

        }

        .select {
            background-color: #0071c0;
            color: #fff !important;
            border-radius: 50%;
        }
    </style>
</head>

<body>
    <div id="calendar-tem">
        
    </div>


    <script>
        (function (window, undefined) {
            var Calendar = function (params) {
                document.getElementById("calendar-tem").innerHTML =
                    ' <button id="preMonth">上个月</button> <button id = "nextMonth"> 下个月 </button> <button id = "today"> 今天 </button> <br> <br>' +
                    '<div id = "date"> </div> <br> <br> <div id = "sign">' + '<div class = "sign-alert">' +
                    '<div class = "sign-week"><span> 一 </span> <span> 二 </span> <span> 三 </span> <span> 四 </span> <span > 五 </span> <span > 六 </span> <span > 日 </span> </div> ' +
                    '<div class = "sign-date"> </div> </div> </div>'
                // var Calendar = function (date, initCb, clickCb) {
                this.date = params.date ? params.date : new Date();
                this.clickCb = params.clickCb || null;
                this.initCb = params.initCb || null;
                this.preMonthEl = document.getElementById("preMonth");
                this.nextMonthEl = document.getElementById("nextMonth");
                this.todayEl = document.getElementById("today");
                this.today;
                this.year;
                this.month;

                this.init();

            }

            Calendar.prototype = {
                constructor: Calendar,
                init: function () {
                    var date = this.date;
                    var year = date.getFullYear(); // 当前年
                    var month = date.getMonth(); // 当前月份 (3 = 4 - 1)
                    var firstday = new Date(year, month, 1); // 当月第一天
                    var weekday = firstday.getDay(); // 当月第一天是星期几
                    var days = new Date(year, month + 1, 0).getDate(); // 当月总天数
                    var today = new Date().getDate(); // 当前天
                    var _year = new Date().getFullYear(); // 当前年
                    var _month = new Date().getMonth(); //当前月
                    this.year = year;
                    this.month = month;
                    this.today = today;

                    if (month == 0) {
                        var premonth = 12;
                        var preyear = year - 1;
                    } else {
                        var premonth = month - 1;
                        var preyear = year;
                    }
                    var prefays = new Date(preyear, premonth + 1, 0).getDate(); // 上个月总天数

                    var res = '';
                    var passdays;
                    if (weekday == 0) {
                        weekday = 7;
                    }
                    passdays = prefays - weekday + 2

                    for (var i = 0; i < weekday - 1; i++) {
                        res += '<div><span class="pass">' + passdays + '</span></div>';
                        passdays++;
                    }
                    for (var j = 1; j <= days; j++) {
                        if (j == today && year == _year && month == _month) {
                            res += '<div data-date="' + j + '"><span  class="on select">' + j +
                                '</span></div>';
                        } else {
                            res += '<div data-date="' + j + '"><span>' + j + '</span></div>';
                        }
                    }
                    var nextdays = 42 - days - weekday + 1;
                    for (var i = 1; i <= nextdays; i++) {
                        res += '<div><span class="pass">' + i + '</span></div>';
                    }
                    document.querySelectorAll(".sign-date")[0].innerHTML = res
                    document.getElementById("date").innerHTML = year + "-" + Number(month + 1);
                    this.datesEl = document.querySelectorAll("div[data-date]");
                    if (this.initCb !== null) {
                        this.initCb(year + "-" + Number(month + 1))
                    }


                    this.bindEvent()

                },
                toToday: function () {
                    var date = new Date();
                    this.date = new Date(date.getFullYear(), date.getMonth(), 1);
                    this.init()
                },
                preMonth: function () {
                    var date = this.date;
                    this.date = new Date(date.getFullYear(), date.getMonth() - 1, 1);
                    this.init()
                },
                nextMonth: function () {
                    var date = this.date;
                    this.date = new Date(date.getFullYear(), date.getMonth() + 1, 1);
                    this.init()
                },
                bindEvent: function () {
                    var _this = this;
                    this.preMonthEl.onclick = function () {
                        _this.preMonth();
                    }
                    this.nextMonthEl.onclick = function () {
                        _this.nextMonth();
                    }
                    this.todayEl.onclick = function () {
                        _this.toToday();
                    }
                    if (_this.clickCb === null) return
                    for (var i = 0; i < this.datesEl.length; i++) {
                        (function (i) {
                            var item = _this.datesEl[i];

                            item.onclick = function () {
                                // console.log(item)
                                var spans = document.getElementsByTagName('span');
                                for (var j = 0; j < spans.length; j++) {
                                    spans[j].classList.remove('select')
                                }
                                item.children[0].classList.add('select')
                                var obj = {
                                    date: _this.year + "-" + Number(_this.month + 1) + "-" +
                                        item.getAttribute("data-date"),
                                    timePeriod: item.getAttribute("data-time-period")
                                }
                                _this.clickCb(obj)
                            }
                        })(i)

                    }
                },
                bindData: function (arr) {
                    var _this = this;
                    var dates = this.datesEl
                    for (var i = 0; i < arr.length; i++) {
                        var item = arr[i]
                        for (var j = 0; j < dates.length; j++) {
                            var cale = dates[j];
                            if (item.date == cale.getAttribute("data-date")) {
                                cale.setAttribute("data-time-period", item.timePeriod)
                                var p = document.createElement("p");
                                var txt = document.createTextNode(item.title);
                                p.appendChild(txt)
                                cale.appendChild(p);
                            }
                        }
                    }
                    if (this.clickCb !== null && _this.year == new Date().getFullYear() && _this.month ==
                        new Date().getMonth()) {
                        var obj = {
                            date: _this.year + "-" + Number(_this.month + 1) + "-" + _this.today,
                            timePeriod: document.querySelector("div[data-date='" + _this.today +
                                    "']")
                                .getAttribute("data-time-period")
                        }
                        this.clickCb(obj)
                    }
                }
            };
            window.Calendar = window.Calendar || Calendar
        }(window));


        var _Calendar = new Calendar({
            date: new Date(),
            clickCb: function (obj) {
                console.log("选中日期回调:", obj);
                // alert("选中日期回调:" + JSON.stringify)
            },
            initCb: function (date) {
                console.log("初始化回调===>", date);
                var data = [{
                        date: 1,
                        title: "早",
                        timePeriod: "00:00-08:00"
                    },
                    {
                        date: 2,
                        title: "中",
                        timePeriod: "01:00-09:00"
                    },
                    {
                        date: 10,
                        title: "晚",
                        timePeriod: "08:00-16:00"
                    },
                    {
                        date: 4,
                        title: "早",
                        timePeriod: "09:00-17:00"
                    },
                    {
                        date: 25,
                        title: "早",
                        timePeriod: "00:00-08:00"
                    },
                ]
                this.bindData(data)
            },
        })
        
   
    </script>
</body>

</html>