zoukankan      html  css  js  c++  java
  • 日历插件原理

    近来要做一个记事本系统,想找一个合适的日历控件,但网上的都是那种日历选择控件。
    于是到qq的记事本系统找了一个,但里面的算法有点落后,所以用了它的样式自己写了个。

    效果:

    <<
    >>
    2018年 3月
            1 2 3
    4 5 6 7 8 9 10
    11 12 13 14 15 16 17
    18 19 20 21 22 23 24
    25 26 27 28 29 30 31

      


    程序说明

    【Date】

    这个日历控件运用了很多Date相关操作和方法。

    先说说Date对象几个有用的属性:
    getFullYear:返回年份值
    getMonth:返回月份值
    getDate:返回一个月中的日期值
    getDay:返回一周中的日期值

    其中对getDay可能比较陌生,下面列出值对应的星期:
    值 星期
    0 星期天
    1 星期一
    2 星期二
    3 星期三
    4 星期四
    5 星期五
    6 星期六

    这几个属性都是根据本地时间获取的,还有getUTCFullYear、getUTCMonth、getUTCDate、getUTCDay这几个属性是全球标准时间对应的值。

    下面说说获取日期对象,获取当前日期很简单:

    new Date()


    获取指定日期:

    new Date(this.options.SelectDay)


    获取指定年月日的日期:

    new Date(this.Year, this.Month - 1, d)


    下面是几个比较有技巧的地方:

    首先,做日历控件时需要知道该月第一天离星期天的天数,参照getDay对应值,发现这刚好等于该月第一天的getDay值,所以可以这样获得:

    new Date(this.Year, this.Month - 1, 1).getDay()

    还有是获取该月的天数,这里比较精妙,通过获取该月最后一天的getDate值就可以得到该月的天数,但没有办法直接获取该月最后一天。
    这里有一个方法,当获取指定年月日的日期时,设置日参数为0,就可以获取上一个月的最后一天,所以可以这样获取:

    new Date(this.Year, this.Month, 0).getDate()


    这个方法是很久以前在别人代码中发现的。

    使用说明:

    首先是实例化一个Calendar,并设置参数。
    参数说明:
    Year:要显示的年份
    Month:要显示的月份
    SelectDay:选择日期
    onSelectDay:在选择日期触发
    onToday:在当天日期触发
    onFinish:日历画完后触发

    一般SelectDay设置成选择了的日期,并在onSelectDay中设置一个函数用来设置这个日期的样式,
    例如实例里SelectDay设置成今个月10号并在那天样式设为onSelect:

    SelectDay: new Date().setDate(10),
    onSelectDay: function(o){ o.className = "onSelect"; },

    而onToday就用来设置今日日期的样式,
    例如实例里面把今天的日期的样式设为onToday:

    onToday: function(o){ o.className = "onToday"; },

    在onFinish中可以放需要设置日历的程序。
    可以通过this.Year和this.Month获取当前日历显示的年份和月份。
    对有数据的日期的也在这里设置,例如实例中是有一个当前月份的有数据的日期列表,然后根据这个列表对相应的日期进行设置:

    Code

    实例中是固定了这个日期列表,实际应用中可以根据年份月份获取对应的日期列表,
    个人推荐用年份月份通过ajax获取。

    程序还有下面这几个方法:
    NowMonth:显示当前月
    PreMonth:显示上一月
    NextMonth:显示下一月
    PreYear:显示上一年
    NextYear:显示下一年
    PreDraw:根据日期参数画日历

    程序代码:


    var $ = function (id) {
        return "string" == typeof id ? document.getElementById(id) : id;
    };

    var Class = {
      create: function() {
        return function() {
          this.initialize.apply(this, arguments);
        }
      }
    }

    var Extend = function(destination, source) {
        for (var property in source) {
            destination[property] = source[property];
        }
        return destination;
    }


    var Calendar = Class.create();
    Calendar.prototype = {
      initialize: function(container, options) {
        this.Container = $(container);//容器(table结构)
        this.Days = [];//日期对象列表
        
        this.SetOptions(options);
        
        this.Year = this.options.Year || new Date().getFullYear();
        this.Month = this.options.Month || new Date().getMonth() + 1;
        this.SelectDay = this.options.SelectDay ? new Date(this.options.SelectDay) : null;
        this.onSelectDay = this.options.onSelectDay;
        this.onToday = this.options.onToday;
        this.onFinish = this.options.onFinish;    
        
        this.Draw();
      },
      //设置默认属性
      SetOptions: function(options) {
        this.options = {//默认值
            Year:            0,//显示年
            Month:            0,//显示月
            SelectDay:        null,//选择日期
            onSelectDay:    function(){},//在选择日期触发
            onToday:        function(){},//在当天日期触发
            onFinish:        function(){}//日历画完后触发
        };
        Extend(this.options, options || {});
      },
      //当前月
      NowMonth: function() {
        this.PreDraw(new Date());
      },
      //上一月
      PreMonth: function() {
        this.PreDraw(new Date(this.Year, this.Month - 2, 1));
      },
      //下一月
      NextMonth: function() {
        this.PreDraw(new Date(this.Year, this.Month, 1));
      },
      //上一年
      PreYear: function() {
        this.PreDraw(new Date(this.Year - 1, this.Month - 1, 1));
      },
      //下一年
      NextYear: function() {
        this.PreDraw(new Date(this.Year + 1, this.Month - 1, 1));
      },
      //根据日期画日历
      PreDraw: function(date) {
        //再设置属性
        this.Year = date.getFullYear(); this.Month = date.getMonth() + 1;
        //重新画日历
        this.Draw();
      },
      //画日历
      Draw: function() {
        //用来保存日期列表
        var arr = [];
        //用当月第一天在一周中的日期值作为当月离第一天的天数
        for(var i = 1, firstDay = new Date(this.Year, this.Month - 1, 1).getDay(); i <= firstDay; i++){ arr.push(0); }
        //用当月最后一天在一个月中的日期值作为当月的天数
        for(var i = 1, monthDay = new Date(this.Year, this.Month, 0).getDate(); i <= monthDay; i++){ arr.push(i); }
        //清空原来的日期对象列表
        this.Days = [];
        //插入日期
        var frag = document.createDocumentFragment();
        while(arr.length){
            //每个星期插入一个tr
            var row = document.createElement("tr");
            //每个星期有7天
            for(var i = 1; i <= 7; i++){
                var cell = document.createElement("td"); cell.innerHTML = "&nbsp;";
                if(arr.length){
                    var d = arr.shift();
                    if(d){
                        cell.innerHTML = d;
                        this.Days[d] = cell;
                        var on = new Date(this.Year, this.Month - 1, d);
                        //判断是否今日
                        this.IsSame(on, new Date()) && this.onToday(cell);
                        //判断是否选择日期
                        this.SelectDay && this.IsSame(on, this.SelectDay) && this.onSelectDay(cell);
                    }
                }
                row.appendChild(cell);
            }
            frag.appendChild(row);
        }
        //先清空内容再插入(ie的table不能用innerHTML)
        while(this.Container.hasChildNodes()){ this.Container.removeChild(this.Container.firstChild); }
        this.Container.appendChild(frag);
        //附加程序
        this.onFinish();
      },
      //判断是否同一日
      IsSame: function(d1, d2) {
        return (d1.getFullYear() == d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate());
      } 
    }



    测试代码:


    var cale = new Calendar("idCalendar", {
        SelectDay: new Date().setDate(10),
        onSelectDay: function(o){ o.className = "onSelect"; },
        onToday: function(o){ o.className = "onToday"; },
        onFinish: function(){
            $("idCalendarYear").innerHTML = this.Year; $("idCalendarMonth").innerHTML = this.Month;
            var flag = [10,15,20];
            for(var i = 0, len = flag.length; i < len; i++){
                this.Days[flag[i]].innerHTML = "<a href='javascript:void(0);' onclick="alert('日期是:"+this.Year+"/"+this.Month+"/"+flag[i]+"');return false;">" + flag[i] + "</a>";
            }
        }
    });

    $("idCalendarPre").onclick = function(){ cale.PreMonth(); }
    $("idCalendarNext").onclick = function(){ cale.NextMonth(); }

    $("idCalendarPreYear").onclick = function(){ cale.PreYear(); }
    $("idCalendarNextYear").onclick = function(){ cale.NextYear(); }

    $("idCalendarNow").onclick = function(){ cale.NowMonth(); }
     
    https://www.cnblogs.com/cloudgamer/archive/2008/08/23/1274459.html
     
  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/Tohold/p/8528693.html
Copyright © 2011-2022 走看看