zoukankan      html  css  js  c++  java
  • [javascript]简单 方便 易折腾的日历控件,纯javascript支持链式语法,核心代码只有5行

    又重复造了个轮子,重复造轮子当然要有优点要不就没有存在价值。使用简单,方便。只要5行代码就可生成年历。

    input date已经是一个原生控件opera和chrome已经支持,日历控件逻辑比较复杂,要做到尽善尽美也是不容易的,也是比较锻炼编码的,所以学习意义大于实际意义。而且这个控件也是多年心愿,最近有时间写写停停,终于坚持下来就拿来和大家分享了。

    传送门

    特点

    1.此日历插件特点在于简单易用,要保证功能实现最低要求一个参数。

    2.个性化配置有强大的自定义事件和多个个性化参数可选。

    3.采用原型继承,扩展派生非常方便。

    4.跨浏览器,保证可用性。

    5.采用表格做载体,无样式也可以正常使用功能。

    6.缓存,已生成月份数据。使数据持久化,减少计算。

    7.无样式支持,功能依然健在。

    应用展示

    a.

    b.

    c.

    技术总结

    1.主要难点不是日期算法,而是select控件和表格所带来的问题。select和表格都有一套自己的dom api,来操作和访问。尤其是生成日历table的算法非了一些时间,而且ie浏览器上。innerHTML属性,table tbody tfoot tr都是只读的,所以对技术选型有一些干扰。中间使用了insertRow这样的方法未果,采用分辨浏览器采用不同方案也行不通后,过段采用整个table都用拼字符串的方式。虽然效率不一定比生成dom节点存入变量修改高,但是结果却是最好的。

    2.select主要问题在于序号和长度差,要访问selectedIndex,设置select的值都要小心这个变化。

    3.Date对象的序号问题,年 日都是从1开始,月份是从0开始,这些差别和人类习惯的处理带来一定成本。

    可见初期,技术储备和技术选型的重要性。

    其实日期核心算法只有5行代码而已,想要生成一个可用的日期控件20行内代码足够,由于和日期控件相关的控件出来带来了大量代码。

    核心代码

     

    1。计算某个月有多少天,2012.6月到底有多少天呢?我们要是知道6月最后一天是多少号,不就知道6月有多少天了吗。

    new Date('2012,6,0').getDate();最简单最短 //chrome不支持用字符串new Date('2012,6,0')格式创建日期, 但支持new Date('2012','6','0');这点要注意 而safari没有问题非常诡异

    通用的

    (new Date(+(new Date(2012, 7, 1)) - 86400000)).getDate();

    下个月的一号减去一天,就是当月最后一天

    2.知道了当月有多少天还不行,要知道当月1号是要放在什么位置,如果知道1号是星期几不就可以知道1号在什么位置了吗。

    new Date(2012, 7,1).getDay();

     

    3.生成一个月的日历,代码很简单只有5行

    for (var i = 0; i < row; i++) {
      html.push('</tr>');
       for (var j = 0; j < 7; j++) {
          html.push((cell-- <= offset && days > 0) ? ('<td ' + (that.Date > new Date(y, m, days + 1) ? 'class="oldDay"' : '') + (y === that.Year && m === that.Month && days === that.Day ? 'class="currentDay"' : '') + ' title="'+y+that.style+(m+1)+that.style+days+'">' + (days--) + '</td>') : '<td></td>');
       }
       html.push('<tr>');
    }

    大家可能要怀疑为什么先写的是 </tr>结束标签,开始生成日历的时候采用的是倒序循环,用li标签,后面发现无样式时不能使用,所以改用table但这一方式保留下来,日期也是按照从后往前生成的。然后调用数组的reverse反向join就正序了。

    4.一个实例的6月份数据和另外一个实例的6月份数据有不同点么,或者重复使用6月份数据需要每次都计算么,答案显然不是。相同月份的数据多次使用要是只计算一次的话就可以大大提高效率,减少计算次数。

    那么这就牵扯到数据持久化的问题,怎样把数据持久化呢或者暂时持久化?答案是把数据保存在类的属性上随用随拿。

    var key = '_date_:' + Y + ':' + M;
    indicotar.cache[key] || (indicotar.cache[key] = that.getDateString(Y, M));
    

    按照年月生成一个key,如果没有数据就调用方法生成数据存入对应key的value。以后只用只用取出,合并字符串即可。

     

    API

    constructor:Cal(可以自行修改无依赖);
    实例化:new Cal(document.body);
    返回值:实例对象;
    参数
    Node *htmlNode nodeType为1的节点,控件会被append此节点内
    Object O 配置控件可选参数
    Number O.Y 设置的年份,默认当年,范围(1970-当年+10)
    Number O.M 设置的月份,默认当月,范围(1-12)
    String O.hasTitle 是否有日期控制栏,默认有'true'
    String O.hasFoot 是否有脚注用来显示年月,默认无'false'
    String O.style 日期分隔符,默认'-'
    Number O.startYear 开始年,默认2006
    Number O.endtYear 结束年,默认当年加10
    Function O.ongetdate 用户点击日期单元格时触发,this指向实例,第一个参数为日期对应数组
    Function O.onrender 控件插入值dom树时触发,this指向实例,第一个参数为控件对应的dom节点
    Function O.ongetdatestring 获得月份所对应的日期字符串时触发,this指向实例,第一个参数为字符串
    Function O.oncalframe 组成完毕控件node框架时触发,this指向实例,第一个参数为对应的dom节点
    Function fn 类的回调函数,生成控件后触发
    实例方法
    方法名 参数 返回值
    createDay Y:number/string(2012),M:number/string(0-11) 实例(1储存日期字符串至Cal的cache中,是数据持久化;2调用render)
    render node:(this.elems),key:string('_date_:2012:0'),Y:number(2012),M:number(0-11) 实例(渲染控件至dom树)
    getDateString Y:number(2012),M:number(0-11) htmlString
    toString   string '2012-12-12' (获取选中日期对应的字符串)
    valueOf   Array [2012,12,12] (获取选中日期对应的数组)
    hide   实例 (隐藏控件)
    show   实例 (显示控件)
    setCss Object({'font-size':'12px','width':'300px'}) 实例 (为控件添加样式)
  • 相关阅读:
    R语言介绍
    mysql存储过程和函数的操作
    在SSRS自动化报表中创建共享数据源
    在python中实现数据库下group by功能
    MySQL中创建表及导入文件
    python下各种包的安装
    windows下python2.7.11的安装
    面向对象(异常)
    面向对象(内部类)
    面向对象(Object类)
  • 原文地址:https://www.cnblogs.com/enix/p/2574663.html
Copyright © 2011-2022 走看看