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
     
  • 相关阅读:
    php获取OS信息
    坑爹的IE quirk模式
    [转]mysql privileges
    [转]VSFTPD的设置选项
    php性能分析工具xhprof
    php扩展安装
    又是万恶的IE....6
    ASP.NET操作文件(文件夹)简单生成html操作示例
    asp.net文件操作类
    c++/clr与c#的性能比较
  • 原文地址:https://www.cnblogs.com/Tohold/p/8528693.html
Copyright © 2011-2022 走看看