日历插件的详解

本插件是在jQuery 1.6.1基础上进行开发的。

 

var _count = 0;

var _expando = "CCalendar-" + (+new Date()) + "-",       

var CCalendar = function(element,options){

  this.initialize.apply(this,arguments);     //在new出来的CCalendar对象的执行上下文中执行initialize方法,并传入参数element,options。

  _count++;              //这里的arguments是[element,options],通过apply方法后,会把数组中的每一项传参给initialize,而不是传数组给它。

}

//默认配置
CCalendar.defcfg = {
  id: null,
  showCount: 1,
  direction: "Right",
  startDate: new Date(),
  maxDate: false,
  minDate: false,
  lang: 'zh-cn',

  onSelect: null,
  onSelectBack: null,
  onHide: null,
 
};

CCalendar.prototype = {

  constructor: CCalendar,  

  initialize: function (element, options) {
    options = options || {};               //如果没有传入对象,就使用空对象
    this.element = $(element);          //把元素转化成jQuery对象
    this.format = GLOBLE.parseFormat(options.format || this.element.data('date-format') || 'yyyy-mm-dd');

      //GLOBLE.parseFormat解析日期的格式,优先级:开发人员传入的格式->元素date-format属性的格式->默认格式'yyyy-mm-dd'
    this.isInput = this.element.is("input");         

    // 合并默认配置
    var dftCfg = CCalendar.defcfg;
    for (var i in dftCfg) {
      if (options[i] === undefined) {   //如果是传入的参数,就不使用默认值
        options[i] = dftCfg[i];
      }
    }

    this.direction = options.direction; //默认提示控件在Right
    options.id = options.id || _expando + _count;     //id为CCalendar-当前日期的毫秒数-当前的_count
    this.picker = $("<div/>", {"id": options.id, "class": "ui-date"}).appendTo('body').bind({
      click: $.proxy(this.click, this)    //$.proxy返回一个新函数,并且这个新函数始终保持了特定的上下文(这里就是this,也就是new出来的CCalendar)
    });      //对这个div,也就是this.picker绑定click事件

     //$.proxy( me.test, me, you, they ),test(you,they,event)。第一个参数为function(点击事件触发的函数),第二个参数为context(函数执行的上下文),第三个参数,以及后面的参数,都会传入到function中去。function中总会有一个event参数。event.type -> click。

    this.create(options);
    //如果是输入框
    if (this.isInput) {
      this.element.bind({
        focus: $.proxy(this.show, this),          //对传入的input元素绑定focus和keyup事件
       
      });
    }

    else {         //如果元素不是input,就对元素绑定click事件

      this.element.bind('click', $.proxy(this.show, this));
    }

  }, 

  //创建日历
  create: function (options) {
    this.setOptions(options);
    this.fill(this.date);
  }, 

  setOptions: function (options) {
    this.options = options;
    this.options.startDate  && (this.options.startDate = GLOBLE.parseDate(this.options.startDate, this.format));    

    //是否传入了日历中显示的选中日期,如果没有就是当前时间的日期,如果有,传入的显示日期必须可以转化成相应的日期格式。默认为:'yyyy-mm-dd'
    this.lang =GLOBLE.lang[this.options.lang];       //默认为'zh-cn'
    (this.options.maxDate && (this.options.maxDate = GLOBLE.parseDate(this.options.maxDate, this.format)));
    (this.options.minDate && (this.options.minDate = GLOBLE.parseDate(this.options.minDate, this.format)));

      //日历控件里面可以选择的日期最大值和最小值,传入的日期必须能够转换成相应的日期格式,默认为:'yyyy-mm-dd'
    this.date = {      //日历上选中的日期,如果没传入startDate参数,那么就是当前时间的日期
      year: this.options.startDate.getFullYear(),
      month: this.options.startDate.getMonth(),
      days: this.options.startDate.getDate()
    };
  }, 

    //构建主体
  fill: function (date) {         //日历上默认被选择的日期
    var dp = this,
    options = dp.options;

    var disabled,
    isShowToday = true,
    year = (date.year || this.date.year),     //其实这里的date和this.date是同一个
    month = (date.month || this.date.month),
    _today = new Date(GLOBLE.today.year, GLOBLE.today.month, GLOBLE.today.date);

      //比如在中国大陆、、香港、新加坡、马来西亚、菲律宾等地区的本地时间比UTC快8小时,记作UTC+8,意思就是比UTC时间快8小时。   

    this.date.year = year,
    this.date.month = month;

    var main = this.dom ? this.dom.main : $("<div/>", {"class": "main"}).appendTo(this.picker);  

      //再新建一个div,添加到id为options.id的div中。我们这里把外层的div叫做div1,main的称作div2。
    main.empty();       //移除元素的所有内容,包括所有文本和子节点。remove,连元素都移除
    for (var i = 0; i < options.showCount; i++) {    //默认情况下为1

      var dayCount = GLOBLE.getDaysInMonth(year, month),  

          //得到当前被选择日期的当前月的天数。(假设今天是2014,3月5号,那么year=2014,month=2)
        prev = GLOBLE.getPNDate(year, (month + 1), -1),    //得到上一个月的日期,{year:2014,month:1,day:28}
        next = GLOBLE.getPNDate(year, (month + 1), 1),    //得到下一个月的日期,{year:2014,month:3,day:30}
        startPad = new Date(year, month, 1).getDay(),

           //得到当前被选择日期的当前月的第一天是星期几,返回值是 0(周日) 到 6(周六) 之间的一个整数。{2014.3.1号是星期六}
        pday,
        list = $("<div/>", {  "class": "ui-date-list ui-month" + i + (options.showCount > 1 && year == GLOBLE.today.year &&

          month == (GLOBLE.today.month + 1) ? 'ui-month-cur' : "")  });  //新建一个div,我们称为div3

      var html = ['<div class="ui-date-head ui-date-top">'];
      (i == 0) && html.push('<a data-action="YEAR_LEFT" class="ui-year-left" href="javascript:void(0)" title="'

          + dp.lang.previousYear + '">&laquo;</a><a data-action="MONTH_LEFT" class="ui-month-left" href="javascript:void(0)" title="'

          + dp.lang.previousMonth + '">&lsaquo;</a>');

            //添加上一年,上一个月的链接,只有i==0时才添加,因为一个日历上只需要一个。
      html.push('<a data-action="SELECT_YEAR" class="ui-year" href="javascript:void(0)" title="' +

          dp.lang.selectYear + '">' + year + '</a>年<a data-action="SELECT_MONTH" class="ui-month" data-year="' + year + '"

          href="javascript:void(0)" data-dom="month" title="' + dp.lang.selectMonth + '" >' +

          (((month + 1) < 10 ? '0' : '') + (month + 1)) + '</a>月');         //如果月份少于10,就添加0,变成09,08这种。{03}
      (i + 1 == options.showCount) && html.push('<a data-action="MONTH_RIGHT" class="ui-month-right" href="javascript:void(0)" title="' +           dp.lang.nextMonth + '">&rsaquo;</a><a data-action="YEAR_RIGHT" class="ui-year-right" href="javascript:void(0)" title="' +           dp.lang.nextYear + '">&raquo;</a>');

            //添加下一月,下一年的链接,也只添加一次。

      html.push('</div><div class="ui-date-content clearfix"><div class="ui-date-week">');
      for (var j = 0; j < 7; j++){

          html.push('<span class="ui-week ' + j + '">' + dp.lang.week[j] + '</span>');     //添加星期一到星期天

      }

      html.push('</div><div class="ui-date-days">');
      var nday = startPad = startPad == 0 ? 6 : startPad - 1;     //假设今天星期六,那么返回6,startPad 和nday等于5.
      for (; startPad >= 0; startPad--) {  //循环6次
           pday = (prev.day - startPad)  //第一次循环时,prev.day=28,startPad =5,pday=23
           _innerDay(prev, pday, true);  //此方法就是把前一个月的23号显示在日历插件上,再循环就是24,25,一直到28号。它的显示样式是隐式的
      }

      for (var j = 1; j <= dayCount; j++) {       //31天,2014年3月
          disabled = false;
          var day = new Date(year, month, j).getDay();   //针对每天,得到是星期几
          html.push('<div class="d-' + day);

          if (options.maxDate && options.maxDate <= new Date(year, month, j) ||     //默认maxDate 为null

            options.minDate && options.minDate >= new Date(year,month, j)) {
              disabled = true;
              html.push(' ui-days-disabled');
          }

          if (GLOBLE.today.year == year && GLOBLE.today.month == month && GLOBLE.today.date == j) {
              html.push(' ui-days-current');         //如果是当天的日期,比如3月5号,也就是j=5时,就让它的class变成current。
              if (disabled) isShowToday = false;
          }
          html.push('"><a data-action="DAY" href="javascript:void(0)" data-year="' + year + '" data-month="' + (month + 1 ) +

            '" data-day="' + j + '" data-disabled="' + disabled + '" data-old="' + (new Date(year, month, j) < _today ? 1 : 0 ) +

              '" >' + j + '</a></div>');

      }
      for (var j = 1; j < 42 - dayCount - nday; j++) {     //42-31-5 = 6,循环5次,因为日历上总共要显示42天
          _innerDay(next, j);        //把下个月的几天显示在日历上,隐式显示。
      }
      html.push('</div></div>');
      list.html(html.join(""));        //把所有的元素添加到list(div3)
      main.append(list);          //再把div3添加到div2中,div2在div1中,div1在body中。
      if (++month == 12) {          //month=2,这时month=3
          year++;
          month = 0;
      }
    }

      if (GLOBLE.ie) {  //如果是ie
        this.picker.width(200 * options.showCount);      //把div1宽度设置为(200*1=200)
        if (GLOBLE.ie == 6) {    //如果是ie6
          var background = $('<div />', {"class": "ui-date-mark"}).css(  //新建一个div称为div4,把宽度和高度设置为div1的宽度和高度

            {
              width: this.picker.innerWidth(),
              height: this.picker.innerHeight()
            }

          ).html('<iframe frameborder="0" src="about:blank" scrolling="no"></iframe>'); //并在div4中装入一个iframe
          this.picker.append(background);  //把div4添加到div1中。这时的html结构就是

            //<div1><div2>日历控件的元素</div2><div4><iframe></iframe></div4></div1>,iframe做垫片,IE6的bug
        }
    }
    this.dom = {      

        //在this上新添加dom属性,等于{},对象里面有一个main属性就是div2,通过对象的属性来引用(div2中有日历控件需要的html标签)。当重新调用fill时,只需要取到div2,并且empty,就可以重新往div2添加元素了(生成新的日历控件内容)

        main: main
    };

    function _innerDay(obj, pday, flag) {
        html.push('<div class="d-' + pday);
        if (options.maxDate && options.maxDate <= new Date(obj.year, obj.month, pday) ||

          options.minDate && options.minDate >= new Date(obj.year, obj.month, pday)) {
            disabled = true;
            html.push(' ui-days-disabled');
        }

        html.push(' ui-days-other">');
        html.push('<a data-action="DAY" href="javascript:void(0)" data-year="' + obj.year + '" data-disabled="' + disabled +

          '" data-month="' + (obj.month + 1 ) + '" data-day="' + pday + '">' + pday + '</a>');
        html.push('</div>');
    }
  },   

  //显示
  show: function (e) {
    

    this.offset();   //设置日历控件显示的位置

    this.picker.show();
    $(window).bind('resize', $.proxy(this.offset, this));     //窗口改变,就会重新计算日历控件的位置。
    if (e) {
      e.stopPropagation();     //已经被 jQuery 做过标准化处理
      e.preventDefault();
    }

    var that = this;
    $(document).one('mousedown', function (ev) {       //当用户点击页面的其他地方时(不是日历控件)就会隐藏日历控件。one方法表明只执行一次回调方法
      if ($(ev.target).closest('.ui-date').length == 0) {  

      //closest方法,从当前元素开始,沿 DOM 树向上遍历,直到找到已应用选择器的一个匹配为止。 返回包含零个或一个元素的 jQuery 对象。由于只有this.packer有.ui-date属性,因此只有点击了this.packer才会有元素,等于0就代表点击的不是页面上的日历控件,因此隐藏

        that.hide();
      }
    });

  },

  offset: function () {

    //jQuery中的.height()、.innerHeight()和.outerHeight(),height就是content的高度,innerHeight是高度+padding,outerHeight是高度+padding+border+(如果传入true,则加上margin,如果传入false或者不传,就不加)

    this.height = this.element.outerHeight();    
    this.width = this.element.outerWidth();
    var offset = this.element.offset();//返回元素的偏移坐标。该方法返回的对象包含两个整型属性:top 和 left,以像素计。此方法只对可见元素有效。

    var top = offset.top,
    left = offset.left,
    ww = $(window).width(),
    pw = this.picker.width();

    var css = { top: top + this.height };  

    //元素偏移页面的高度+元素的高度(不包括margin),这时日历控件就可以显示在元素的下面了(刚好在元素的border下)。
    switch (this.direction) {      //默认为Right
      case "Left":
        css.left = left >= pw ? (left - pw ) + this.width : left
        break;
      case "Right":   //日历控件的left等于元素的left,左对齐显示。如果超过了窗口的宽度,就让日历控件跟元素右对齐
        css.left = ww <= (pw + left) ? left - pw + this.width : left
        break;
    }

    this.picker.css(css);
  },

  //隐藏
  hide: function () {
    this.picker.hide();    //日历控件隐藏

    typeof this.options.onHide == "function" && this.options.onHide.call(this);  
  },  

//监听点击事件,点击日历时,触发
  click: function (e) {
    e.stopPropagation();
    e.preventDefault();
    var dp = this,
    options = dp.options,
    target = $(e.target).closest('a')[0];    

      //看用户点击的是哪个链接元素,针对不同的链接元素进行不同处理,因此在创建日历控件的时候,只要是a链接的都会响应click事件
    if (!target) return false;          //如果点击的是日历控件上的其他位置,没有a链接的,将不做任何处理
    if (target.getAttribute('data-disabled') == "true") return false;  

      //如果是禁止的选项,比如,定义了最大日期和最小日期,那其他范围的日期,点击也不做任何处理
    var action = target.getAttribute('data-action');   //除了有a链接,还必须保证a链接上有data-action属性,此插件就是通过data-action来调用不同的回调方法。
    if (!action) return false;

    switch (action) {
      case "SELECT_YEAR":    //点击日历控件上的年份时,会弹出一个近10年的选择框,用户可以针对这个选择框点击上一页(上一个10年)和下一页|(下一个十年)
        {
          dp.createYearModel(dp.date.year, target);
        }
        break;
      case "PREV-10-YEAR":      //如果点击年份选择框中的上十年或者下十年,就重新生成新的十年选择框
      case "NEXT-10-YEAR":
        {
          dp.createYearModel(parseInt(target.getAttribute("data-year")), null);
        }
        break;
      case "SELECT_MONTH":     //点击月份,就会弹出一个12个选项(从1到12)的月份选择框
        {
          dp.createMonthModel(dp.date.month, target);    //实现方案跟年份的差不多,没年份的复杂,因为月份没有上十月和下十月,只有12个月
        }
        break;
      case "YEAR":        //当点击年份选择框中的年份时,就触发
        {
          dp.fill({
            year: parseInt(target.getAttribute("data-year"))       //重新生成新的日期时间
          });
        }
        break;
      case "MONTH":
        {
          dp.fill({
            month: parseInt(target.getAttribute("data-month") - 1)       //重新生成新的日期时间
          });
        }
        break;
      case "DAY":
        {
          this.select(target);      //选择日时,就会选择这个日期
        }
        break;
      case "YEAR_LEFT":         //日历控件还有上一年的按钮
        {
          dp.date.year -= options.showCount;        //年份减少一年,showCount默认为1
          dp.fill(dp.date);     //重新生成日期
        }
        break;
      case "YEAR_RIGHT":           //以此类推
        {
          dp.date.year += options.showCount;     
          dp.fill(dp.date);
        }
        break;
      case "MONTH_LEFT":            //以此类推
        {
          dp.date.month -= options.showCount;
          if (dp.date.month < 0) {
            dp.date.month = dp.date.month + 12;
            dp.date.year--;
          }
          dp.fill(dp.date);
        }
        break;
      case "MONTH_RIGHT":     //以此类推
        {
          dp.date.month += options.showCount;
          if (dp.date.month > 11) {
            dp.date.month = dp.date.month - 12;
            dp.date.year++;
          }
          dp.fill(dp.date);
        }
        break;
      default :
          {
          }
    }
  }, 

  select: function (target) {
    var dp = this,
    options = dp.options;

    var yyyy = target.getAttribute('data-year'),     //得到当前的年份
      yy = yyyy.substr(2),
      m = parseInt(target.getAttribute('data-month')),      //得到当前的月份
      mm = m < 10 ? '0' + m : m,      //格式化为两位的月份
      d = parseInt(target.getAttribute('data-day')),    //得到当前的天
      dd = d < 10 ? '0' + d : d,     //格式化天为两位数
      date = new Date(yyyy, m - 1, d),     
      time = date.getTime(),
      back = GLOBLE.formatDate(date, dp.format),    //把当前选择的日期格式化
      backData = {      //传给回调方法的json对象,使之可以使用各种格式的日期数据
        yyyy: yyyy,
        yy: yy,
        mm: mm,
        m: m,
        dd: dd,
        d: d,
        back: back,
        date: date,
        time: time
      };

    //选择日期前
    if (this.options.onSelect && !this.options.onSelect.call(dp, backData))     //如果传入onSelect调用后,传入选择的日期,返回false,则不做任何处理

      return null;   //这里可以让开发人员传入对象时,写上onSelect方法,然后在方法里面,判断选择的日期是否可选
    if (!dp.isInput) {
        
        dp.element.find('input').prop('value', back);    //如果元素不是input,就去找input,然后显示出来
       
        dp.element.data('date', back);
    }

    else {
        dp.element.prop('value', back);    //把日期显示在input框中
     }

    //选择日期后
    if (!this.options.onSelectBack || ( this.options.onSelectBack && this.options.onSelectBack.call(dp, backData) === true)) {

      //如果传入onSelectBack方法,那么选择日期,并显示在input后,如果 onSelectBack方法根据选择的日期返回true,就隐藏,如果返回false,就不隐藏日历,让用户继续选择。
      dp.hide();    //隐藏日历控件
    }
  },

  //创建月份面板
  createMonthModel: function (month, target) {
    var self = this,
    list = $(".ui-month-list", self.dom.main);

    if (list.length == 0) {
      list = $("<div/>", {"class": "ui-month-list"});
      self.dom.main.append(list);
      self.dom["month"] = list;
      self.dom.main.bind("mousedown", function (ev) {
        if ($(ev.target).closest('.ui-month-list').length == 0) {
          list.hide();
        }
        return false;
      });
    }

    if (target) {
      var offset = $(target).position();
      list.css({
        top: offset.top + 26,
        left: offset.left - 23 / 2
      }).show();
    }

    var items = [];

    for (var i = 1; i <= 12; i++) {
      items.push({
        value: i,
        label: i,
        role: 'MONTH'
      });
    }

    var current = {
      value: month,
      label: month
    };
    var html = [];
    for (var j = 0, l = items.length; j < l; j++) {
      var m = items[j]
      html.push('<a href="javascript:void(0)" data-action="' + m.role + '" class="' + (m.value < GLOBLE.today.month + 1 ? " ui-date-old" : "") + (m.value == GLOBLE.today.month + 1 ? " ui-date-current" : "") + '" data-month="' + m.value + '">' + m.label + '</a>');

    }
    list.html(html.join(""));
  },

  //创建年份面板
  createYearModel: function (year, target) {     //传入的是当前的年份,也就是2014,
    var self = this,
    years = $(".ui-year-list", self.dom.main);

    if (years.length == 0) {
      years = $("<div/>", {"class": "ui-year-list"});   //如果没有显示年份的选择框,就新建一个div,表示year
      self.dom.main.append(years);
      self.dom["year"] = years;
      self.dom.main.bind("mousedown", function (ev) {
        if ($(ev.target).closest('.ui-year-list').length == 0) {
          years.hide();
        }
        return false;
      });
    }

    if (target) {        //把这个年份的选择框,定位到日历年份的位置
      var offset = $(target).position();
      years.css({
        top: offset.top + 17,
        left: offset.left - 37 / 2
      }).show();
    }

    var items = [     //item数组的第一项是上十年的按钮
    {
      value: year - 10,
      label: '&laquo;',
      role: 'PREV-10-YEAR'
    }
    ];

    for (var i = year - 6; i < year + 4; i++) {     //前6年,当前年份,后3年

      items.push({
        value: i,
        label: i,
        role: 'YEAR'
      });
    }
    items[7] = {value: year, label: year, role: 'YEAR', current: true};
    items.push({       ////item数组的最后一项是下十年的按钮
      value: year + 10,
      label: '&raquo;',
      role: 'NEXT-10-YEAR'
    });

    var current = {    //当前年份,也就是2014
      value: year,
      label: year
    };
    var html = [];
    for (var j = 0, l = items.length; j < l; j++) {   //针对items数组,创建这个年份的选择框
      var y = items[j]
      html.push('<a href="javascript:void(0)" data-action="' + y.role + '" class="' + (y.value < GLOBLE.today.year ? " ui-date-old" : "") + (y.value ==       GLOBLE.today.year ? " ui-date-current" : "") + '" data-year="' + y.value + '">' + y.label + '</a>');

    }
    years.html(html.join(""));
  },

 

    

}

var GLOBLE = {
  ie: document.all && navigator.userAgent.match(/\s{1}\d{1}/),
  //语言包
  lang: {
    "zh-cn": {
      week: ['日', '一', '二', '三', '四', '五', '六'],
      previousMonth: '上一月',
      nextMonth: '下一月',
      previousYear: '上一年',
      nextYear: '下一年',
      selectYear: '选择年',
      selectMonth: '选择月',
      more: '更多',
      today: '今'
    },

    "en":{

        .....    //英文,国际化

    }
  },
    //今天
  today: {
    year: new Date().getFullYear(),
    month: new Date().getMonth(),
    date: new Date().getDate()
  },
    //是否是闰年
  isLeapYear: function (year) {
    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
  },
  //获取月份的天数
  getDaysInMonth: function (year, month) {
    return [31, (GLOBLE.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
  },
    //获取上下月
  getPNDate: function (year, month, path) {
    if ((month += (path || 0)) < 1) {
      month = 12;
      year--;
    }

    else if (month > 12) {
      month = 1;
      year++;
    }
    var date = new Date(year, month, 0);
    return {
      year: date.getFullYear(),
      month: date.getMonth(),
      day: date.getDate()
    };
  },
    //转换为格式对象
  parseFormat: function (format) {
    var separator = format.match(/[.\/\-\s].*?/), parts = format.split(/\W+/);
    if (!separator || !parts || parts.length === 0) {
      throw new Error("Invalid date format.");
     }
    return {
      separator: separator,
      parts: parts
    };
  },
  //按照格式对象,格式化字符日期
  parseDate: function (date, format) {
    var parts = date.split(format.separator), date = new Date(), val;
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    if (parts.length === format.parts.length) {
      var year = date.getFullYear(), day = date.getDate(), month = date.getMonth();
      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
        val = parseInt(parts[i], 10) || 1;
        switch (format.parts[i]) {
          case 'dd':
          case 'd':
            day = val;
            date.setDate(val);
            break;
          case 'mm':
          case 'm':
            month = val - 1;
            date.setMonth(val - 1);
            break;
          case 'yy':
            year = 2000 + val;
            date.setFullYear(2000 + val);
            break;
          case 'yyyy':
            year = val;
            date.setFullYear(val);
            break;
          }
      }
      date = new Date(year, month, day, 0, 0, 0);
    }
    return date;
  },
  //把日期格式化日期字符串(format的格式)
  formatDate: function (date, format) {
    var val = {
      d: date.getDate(),
      m: date.getMonth() + 1,
      yy: date.getFullYear().toString().substring(2),
      yyyy: date.getFullYear()
    };
    val.dd = (val.d < 10 ? '0' : '') + val.d;
    val.mm = (val.m < 10 ? '0' : '') + val.m;
    var date = [];
    for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
      date.push(val[format.parts[i]]);
    }
    return date.join(format.separator);
  }
};

假设现在你有一个input元素需要绑定日历控件,那么只需要var date = new CCalendar(input元素,{})。这时将调用create方法创建日历,但是不显示,当input元素获得焦点时,就会触发show方法,显示出来。你可以在第二个参数中,传入json对象,比如:maxDate(可选择的最大日期),minDate(可选择的最小日期),lang(语言版本,中文,英文),onSelect(选择日期前,触发的方法),onHide(隐藏日期后,触发的方法),onSelectBack(选择日期后,触发的方法)等属性值。

如果你需要弄成jQuery插件,或者弄到sea.js模块加载中去,请看:http://www.cnblogs.com/chaojidan/p/4213942.html

 

 

加油!

你可能感兴趣的:(插件)