最近开始整理咱们的单页应用框架了,虽然可能比不上MVVM模式的开发效率,也可能没有Backbone框架模块清晰,可是好歹也是本身开发出来javascript
并且也用于了这么多频道的东西,若是没有总结,没有整理,没有开源就太惋惜了......因此最近开始整理框架相关的东西,争取抽象一点东西出来css
框架出来还须要一点时间,可是框架会须要相关的UI库,这个东西能够先有思路,最后再根据框架作一点调整吧html
日历对于UI插件而言仍是比较难的,里面涉及到的东西不少,就阴历与阳历一块就有不少东西,而后涉及到不少算法,其中节日的设置更是有必定动态性java
各类各样的需求也是莫名其妙,因此咱们今天便来实现一个简单的日历插件吧,固然他的主要应用场景仍是单页应用算法
首先,咱们这里用这套东西实现继承api
var arr = []; var slice = arr.slice; function create() { if (arguments.length == 0 || arguments.length > 2) throw '参数错误'; var parent = null; //将参数转换为数组 var properties = slice.call(arguments); //若是第一个参数为类(function),那么就将之取出 if (typeof properties[0] === 'function') parent = properties.shift(); properties = properties[0]; function klass() { this.initialize.apply(this, arguments); } klass.superclass = parent; klass.subclasses = []; if (parent) { var subclass = function () { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } var ancestor = klass.superclass && klass.superclass.prototype; for (var k in properties) { var value = properties[k]; //知足条件就重写 if (ancestor && typeof value == 'function') { var argslist = /^\s*function\s*\(([^\(\)]*?)\)\s*?\{/i.exec(value.toString())[1].replace(/\s/i, '').split(','); //只有在第一个参数为$super状况下才须要处理(是否具备重复方法须要用户本身决定) if (argslist[0] === '$super' && ancestor[k]) { value = (function (methodName, fn) { return function () { var scope = this; var args = [function () { return ancestor[methodName].apply(scope, arguments); } ]; return fn.apply(this, args.concat(slice.call(arguments))); }; })(k, value); } } klass.prototype[k] = value; } if (!klass.prototype.initialize) klass.prototype.initialize = function () { }; klass.prototype.constructor = klass; return klass; }
其次,咱们的日历作出来应该是可定制化的,可定制化的粒度控制到每个单元格,意思是每个单元格是可操做的数组
这个时候最好的解决办法就是模板,而且释放一个操做某个日期的接口,好比咱们如今要实现阴历节日或者阳历节日彻底是实现抽象的日历,这样能够最大的提升扩展性app
因此,咱们这里的第一步是实现一个最基本的抽象日历框架
像日历这类插件,我首先仍是想到用表格来作,可是CSS3的出现也能让咱们的代码很好的实现,因此我这里使用li作,具体实现咱们后面再说,咱们要完成的第一个事情是dom
咱们作的第一个事情是给一个日期,而后当月的数据便出来了,好比咱们这里给的是20140420,就是当前日期,而后便须要造成这个月的日期,这里就涉及到一连串东西了
解决这个问题,咱们须要第一个api,算出给定日期一共有多少天,第二步即是排列第一个日期为星期几便可
众所周知,计算月份天数时候有一个例外的状况即是闰年的二月,因此咱们须要检查是否为闰年的接口,这个接口通常由公共日期类库提供
因此咱们在作日历相关的过程当中,彻底能够整理一套日期的API出来,这也是今天一个任务
这里首先给出两个接口,一个判断是否为闰年,一个判断一个月有多少天
var dateUtil = { // @description 是否为闰年 // @param year {num} 多是年份或者为一个date时间 // @return {boolean} 返回值 isLeapYear: function (year) { //传入为时间格式须要处理 if ((typeof year == 'object') && (year instanceof Date)) year = year.getFullYear() if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true; else return false; }, // @description 获取一个月份的天数 // @param year {num} 多是年份或者为一个date时间 // @param year {num} 月份 // @return {num} 返回天数 getDaysOfMonth: function (year, month) { if ((typeof year == 'object') && (year instanceof Date)) { month = year.getmonth() + 1; //注意此处月份要加1 year = year.getFullYear(); } return [31, dateUtil.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; } };
官方的getDay便可返回某天为星期几
0-6:星期天-星期六
因此,理论上咱们给一个日期,就能够得到那一天的dom结构了,咱们来试试,获取本月的日历数据
这里咱们须要新增一个API告诉咱们一年中的某一个月是由周几开始的
// @description 获取一个月份1号是星期几,注意此时的月份传入时须要自主减一 // @param year {num} 多是年份或者为一个date时间 // @param year {num} 月份 // @return {num} 当月一号为星期几0-6 getBeginDayOfMouth: function (year, month) { if ((typeof year == 'object') && (year instanceof Date)) { month = year.getMonth(); //注意此处月份要加1 year = year.getFullYear(); } var d = new Date(year, month, 1); return d.getDay(); }
这个时候咱们尝试生成咱们的dom结构就出来了:
<style type="text/css"> ul, li { padding: 0; margin: 0; } .cui_calendar, .cui_week { list-style: none; } .cui_calendar li, .cui_week li { float: left; width: 14%; overflow: hidden; padding: 4px 0; text-align: center; } </style>
咱们这里作一次简单的封装后,开始引入模板相关的东西,因而最后造成的东西:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <style type="text/css"> ul, li { padding: 0; margin: 0; } .cui_calendar, .cui_week { list-style: none; } .cui_calendar li, .cui_week li { float: left; width: 14%; overflow: hidden; padding: 4px 0; text-align: center; } </style> </head> <body> <script src="zepto.js" type="text/javascript"></script> <script src="underscore-min.js" type="text/javascript"></script> <script type="text/javascript"> var arr = []; var slice = arr.slice; /** * @description inherit方法,js的继承,默认为两个参数 * @param {function} supClass 可选,要继承的类 * @param {object} subProperty 被建立类的成员 * @return {function} 被建立的类 */ var inherit = function () { // @description 参数检测,该继承方法,只支持一个参数建立类,或者两个参数继承类 if (arguments.length == 0 || arguments.length > 2) throw '参数错误'; var parent = null; // @description 将参数转换为数组 var properties = slice.call(arguments); // @description 若是第一个参数为类(function),那么就将之取出 if (typeof properties[0] === 'function') parent = properties.shift(); properties = properties[0]; // @description 建立新类用于返回 function klass() { this.initialize.apply(this, arguments); } klass.superclass = parent; klass.subclasses = []; if (parent) { // @description 中间过渡类,防止parent的构造函数被执行 var subclass = function () { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } var ancestor = klass.superclass && klass.superclass.prototype; for (var k in properties) { var value = properties[k]; //知足条件就重写 if (ancestor && typeof value == 'function') { var argslist = /^\s*function\s*\(([^\(\)]*?)\)\s*?\{/i.exec(value.toString())[1].replace(/\s/i, '').split(','); //只有在第一个参数为$super状况下才须要处理(是否具备重复方法须要用户本身决定) if (argslist[0] === '$super' && ancestor[k]) { value = (function (methodName, fn) { return function () { var scope = this; var args = [function () { return ancestor[methodName].apply(scope, arguments); } ]; return fn.apply(this, args.concat(slice.call(arguments))); }; })(k, value); } } klass.prototype[k] = value; } if (!klass.prototype.initialize) klass.prototype.initialize = function () { }; klass.prototype.constructor = klass; return klass; }; var dateUtil = { // @description 是否为闰年 // @param year {num} 多是年份或者为一个date时间 // @return {boolean} 返回值 isLeapYear: function (year) { //传入为时间格式须要处理 if ((typeof year == 'object') && (year instanceof Date)) year = year.getFullYear() if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true; else return false; }, // @description 获取一个月份的天数 // @param year {num} 多是年份或者为一个date时间 // @param year {num} 月份 // @return {num} 返回天数 getDaysOfMonth: function (year, month) { if ((typeof year == 'object') && (year instanceof Date)) { month = year.getMonth(); //注意此处月份要加1,因此咱们要减一 year = year.getFullYear(); } return [31, dateUtil.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; }, // @description 获取一个月份1号是星期几,注意此时的月份传入时须要自主减一 // @param year {num} 多是年份或者为一个date时间 // @param year {num} 月份 // @return {num} 当月一号为星期几0-6 getBeginDayOfMouth: function (year, month) { if ((typeof year == 'object') && (year instanceof Date)) { month = year.getMonth(); //注意此处月份要加1 year = year.getFullYear(); } var d = new Date(year, month, 1); return d.getDay(); } }; var Calendar = inherit({ initialize: function () { this.dateObj = new Date(); this.rootBox = $('body'); //星期项目模板 this.weekDayItemTmpt = "<li><%=['日', '一', '二', '三', '四', '五', '六'][day] %></li>"; //星期包裹层模板,传入今天星期几,内部怎么实现本身来 this.weekDayTmpt = '<ul class="cui_week"><%for(var day = 0; day < 7; day++) { %> ' + this.weekDayItemTmpt + ' <%} %></ul>'; //各个单元格的模板,能够重写 this.itemTmpt = '<li class="cui_calendar_item"><%=day %></li>'; //无效项目模板 this.invalidTmpt = '<li class="cui_invalid"></li>'; //月份模板,给定当前年月,以及天数,第一天星期几,让用户本身构造月度日历模板 this.mouthTmpt = [ '<ul class="cui_calendar">', '<% for(var i = 0; i < _beginWeek; i++) { %>', this.invalidTmpt, '<% } %>', '<% for(i = 0; i < days; i++) { %>', '<% day = i + 1; %>', this.itemTmpt, '<% } %>', '</ul>' ].join(''); this._initDom(); }, _initDom: function () { var d = this.dateObj; //获取天数 var days = dateUtil.getDaysOfMonth(d); //获取那个月第一天时星期几 var _beginWeek = dateUtil.getBeginDayOfMouth(d); var weekDom = _.template(this.weekDayTmpt)(); var calendarDom = _.template(this.mouthTmpt, { _beginWeek: _beginWeek, days: days }); this.rootBox.append(weekDom); this.rootBox.append(calendarDom); } }); var c = new Calendar(); </script> </body> </html>
var Calendar = inherit({ initialize: function () { this.dateObj = new Date(); this.rootBox = $('body'); //星期项目模板 this.weekDayItemTmpt = "<li><%=['日', '一', '二', '三', '四', '五', '六'][day] %></li>"; //星期包裹层模板,传入今天星期几,内部怎么实现本身来 this.weekDayTmpt = '<ul class="cui_week"><%for(var day = 0; day < 7; day++) { %> ' + this.weekDayItemTmpt + ' <%} %></ul>'; //各个单元格的模板,能够重写 this.itemTmpt = '<li class="cui_calendar_item"><%=day %></li>'; //无效项目模板 this.invalidTmpt = '<li class="cui_invalid"></li>'; //月份模板,给定当前年月,以及天数,第一天星期几,让用户本身构造月度日历模板 this.mouthTmpt = [ '<ul class="cui_calendar">', '<% for(var i = 0; i < _beginWeek; i++) { %>', this.invalidTmpt, '<% } %>', '<% for(i = 0; i < days; i++) { %>', '<% day = i + 1; %>', this.itemTmpt, '<% } %>', '</ul>' ].join(''); this._initDom(); }, _initDom: function () { var d = this.dateObj; //获取天数 var days = dateUtil.getDaysOfMonth(d); //获取那个月第一天时星期几 var _beginWeek = dateUtil.getBeginDayOfMouth(d); var weekDom = _.template(this.weekDayTmpt)(); var calendarDom = _.template(this.mouthTmpt, { _beginWeek: _beginWeek, days: days }); this.rootBox.append(weekDom); this.rootBox.append(calendarDom); } });
这里将许多可能定制化的东西以模板的方式提了出来,好比咱们的week,好比咱们的月份模板,这里各个业务同事能够分别按照本身的需求进行扩展
这里定制的粒度彻底由开发人员决定,他能够只定制各个项目,或者定制整个月份的模板,固然,咱们这里须要传入的参数还不够,还须要增长
好比,咱们要在每个月上面显示当前是某年某月就须要更多的数据了,模板的扩展程度,不少时候取决于数据的完善性,这里年月属性咱们都须要传入
因此咱们模板处能够稍做修改就变成这个样子了:
var c = new Calendar({ mouthTmpt: [ '<div style="overflow: hidden; width: 100%; text-align: center;"><%=year %>年-<%=mouth %>月</div>', '<ul class="cui_calendar">', '<% for(var i = 0; i < beginWeek; i++) { %>', '<li class="cui_invalid"></li>', '<% } %>', '<% for(i = 0; i < days; i++) { %>', '<% day = i + 1; %>', '<li class="cui_calendar_item"><%=day %></li>', '<% } %>', '</ul>' ].join('')
又或者,咱们想让周末变成橙色的话,咱们须要这么干,而且再加一点数据,咱们直接告诉每项当前的年月日,因此他本身能够作不少判断
var c = new Calendar({ itemTmpt: '<li class="cui_calendar_item" <% var d = new Date(year, month, day);
if(d.getDay() == 0 || d.getDay() == 6) %>style="color: orange; "<% %> ><%=day %></li>' });
而后咱们得将相关属性赋予dom结构的一个属性,方便后续操做,不少时候事件相关咱们仍是得依赖dom之间的映射,动态为每一个dom增长data-date属性,年月日之间-分割
由于日模板能够被复写,因此这里须要一个规范,若是这个规范没有了,可能致使日期操做失效
咱们知道日期的月份由0开始,咱们如今是四月,因此对应的月份却应该是3月
通过前面的学习,咱们简单的日历原型其实应该出来了,如今要对其中代码作一些优化
PS:其实如今代码比较少,优化点很少,咱们首先将构造星期与日历相关dom结构的两个方法分离出来
_getWeekDom: function () { return _.template(this.weekDayTmpt)(); }, //description 得到某月的dom结构 _getMonthDom: function (year, month) { var d = new Date(year, month); //description 获取天数 var days = dateUtil.getDaysOfMonth(d); //description 获取那个月第一天时星期几 var _beginWeek = dateUtil.getBeginDayOfMouth(d); var weekDom = _.template(this.weekDayTmpt)(); return _.template(this.mouthTmpt, { year: d.getFullYear(), month: d.getMonth(), beginWeek: _beginWeek, days: days }); }, init: function () { this.rootBox.append(this._getWeekDom()); this.rootBox.append(this._getMonthDom(this.dateObj.getFullYear(), this.dateObj.getMonth())); }
其次,这里的dateObj比较关键,一旦出问题就会致使许多错误,因此咱们最开始应该有一个验证的方法,验证是不是日期的方法固然该由dateUtil提供
这里不但须要验证是否为日期,还须要提供新的日期格式化方法,parseDate方法,用于转变经常使用日期字符串为日期
首先验证日期咱们简单一点
isDate: function (d) { if ((typeof d == 'object') && (d instanceof Date)) return true; return false; },
而后是比较复杂的转换字符串为日期对象,以及转换日期对象为经常使用字符串
这句话的思考是能够匹配各类咱们认为是日期格式的字符串,咱们只须要告诉年月日的格式化方式或者位置便可,好比如下几种
2014年4月20日、2014420、2014-4-20、2014 4 20、2041/4/20
1 //将字符串转换为日期 2 //支持格式y-m-d ymd (y m r)以及标准的 3 parse: function (dateStr, formatStr) { 4 if (typeof dateStr === 'undefined') return null; 5 if (typeof formatStr === 'string') { 6 //首先取得顺序相关字符串 7 var arrStr = formatStr.replace(/[^ymd]/g, '').split(''); 8 if (!arrStr) return null; 9 var formatStr = formatStr.replace('y', '(\\{b}{4})'); 10 var formatStr = formatStr.replace('m', '(\\{b}{1,2})'); 11 var formatStr = formatStr.replace('d', '(\\{b}{1,2})'); 12 var formatStr = formatStr.replace(/\{b\}/g, 'd'); 13 14 var reg = new RegExp(formatStr, 'g'); 15 var arr = reg.exec(dateStr) 16 17 var dateObj = {}; 18 for (var i = 0, len = arrStr.length; i < len; i++) { 19 dateObj[arrStr[i]] = arr[i + 1]; 20 } 21 return new Date(dateObj['y'], dateObj['m'], dateObj['d']); 22 } 23 return null; 24 },
由于楼主正则不是很好,上面的代码应该不是最优写法,基本调用方法以下:
console.log( dateUtil.parse('2012-4-1', 'y-m-d')); console.log(dateUtil.parse('2/4/2014', 'd/m/y')); console.log(dateUtil.parse('2014 4 3', 'y m d')); console.log(dateUtil.parse('2014年4月4日', 'y年m月d日')); console.log(dateUtil.parse('2012-04-05', 'y-m-d')); console.log(dateUtil.parse('06/4/2014', 'd/m/y')); console.log(dateUtil.parse('2014 4 07', 'y m d')); console.log(dateUtil.parse('2014年4月08日', 'y年m月d日')); //输出结果 Tue May 01 2012 00:00:00 GMT+0800 (中国标准时间) 01.htm:229 Fri May 02 2014 00:00:00 GMT+0800 (中国标准时间) 01.htm:230 Sat May 03 2014 00:00:00 GMT+0800 (中国标准时间) 01.htm:231 Sun May 04 2014 00:00:00 GMT+0800 (中国标准时间) 01.htm:232 Sat May 05 2012 00:00:00 GMT+0800 (中国标准时间) 01.htm:233 Tue May 06 2014 00:00:00 GMT+0800 (中国标准时间) 01.htm:234 Wed May 07 2014 00:00:00 GMT+0800 (中国标准时间) 01.htm:235 Thu May 08 2014 00:00:00 GMT+0800 (中国标准时间)
从结果来看,返回时正确的,如果有什么不对,就再说吧。。。。。。
上面咱们将特殊字符串转换为了日期,咱们还得有个借口将日期格式化为须要的字符串
这个网上有一个很不错的方案,这里直接抄了。。。。。。
console.log(dateUtil.format('YYYY年MM月DD日')); console.log(dateUtil.format('YYYY-MM-DD')); 2014年4月20日 01.htm:251 2014-4-20
稍有不足即是没有进行1与01相关的选择,咱们这里稍做修改,并且这里对咱们上面的代码优化提出了方案,咱们一并修改
function formatDate(date, format) { if (arguments.length < 2 && !date.getTime) { format = date; date = new Date(); } typeof format != 'string' && (format = 'YYYY年MM月DD日 hh时mm分ss秒'); var week = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', '日', '一', '二', '三', '四', '五', '六']; return format.replace(/YYYY|YY|MM|DD|hh|mm|ss|星期|周|www|week/g, function(a) { switch (a) { case "YYYY": return date.getFullYear(); case "YY": return (date.getFullYear()+"").slice(2); case "MM": return date.getMonth() + 1; case "DD": return date.getDate(); case "hh": return date.getHours(); case "mm": return date.getMinutes(); case "ss": return date.getSeconds(); case "星期": return "星期" + week[date.getDay() + 7]; case "周": return "周" + week[date.getDay() + 7]; case "week": return week[date.getDay()]; case "www": return week[date.getDay()].slice(0,3); } }); }
format: function (date, formatStr) { if (arguments.length < 2 && !date.getTime) { format = date; date = new Date(); } typeof format != 'string' && (format = 'Y年M月D日 H时F分S秒'); return format.replace(/Y|y|M|m|D|d|H|h|F|f|S|s/g, function (a) { switch (a) { case "y": return (date.getFullYear() + "").slice(2); case "Y": return date.getFullYear(); case "m": return date.getMonth() + 1; case "M": return dateUtil.formatNum(date.getMonth() + 1); case "d": return date.getDate(); case "D": return dateUtil.formatNum(date.getDate()); case "h": return date.getHours(); case "H": return dateUtil.formatNum(date.getHours()); case "f": return date.getMinutes(); case "F": return dateUtil.formatNum(date.getMinutes()); case "s": return date.getSeconds(); case "S": return dateUtil.formatNum(date.getSeconds()); } }); },
因为这里月与分钟都是以m开头,这里会有问题,因此我这里可耻的将分改成F。。。。。。
对应日期处理工厂如今变成这个样子了
1 var dateUtil = { 2 formatNum: function (n) { 3 if (n < 10) return '0' + n; 4 return n; 5 }, 6 //将字符串转换为日期 7 //支持格式y-m-d ymd (y m r)以及标准的 8 parse: function (dateStr, formatStr) { 9 if (typeof dateStr === 'undefined') return null; 10 if (typeof formatStr === 'string') { 11 //首先取得顺序相关字符串 12 var arrStr = formatStr.replace(/[^ymd]/g, '').split(''); 13 if (!arrStr && arrStr.length != 3) return null; 14 15 var formatStr = formatStr.replace(/y|m|d/g, function (k) { 16 switch (k) { 17 case 'y': return '(\\d{4})'; 18 case 'm': ; 19 case 'd': return '(\\d{1,2})'; 20 } 21 }); 22 23 var reg = new RegExp(formatStr, 'g'); 24 var arr = reg.exec(dateStr) 25 26 var dateObj = {}; 27 for (var i = 0, len = arrStr.length; i < len; i++) { 28 dateObj[arrStr[i]] = arr[i + 1]; 29 } 30 return new Date(dateObj['y'], dateObj['m'], dateObj['d']); 31 } 32 return null; 33 }, 34 //将日期格式化为字符串 35 format: function (date, formatStr) { 36 if (arguments.length < 2 && !date.getTime) { 37 format = date; 38 date = new Date(); 39 } 40 typeof format != 'string' && (format = 'Y年M月D日 H时F分S秒'); 41 return format.replace(/Y|y|M|m|D|d|H|h|F|f|S|s/g, function (a) { 42 switch (a) { 43 case "y": return (date.getFullYear() + "").slice(2); 44 case "Y": return date.getFullYear(); 45 case "m": return date.getMonth() + 1; 46 case "M": return dateUtil.formatNum(date.getMonth() + 1); 47 case "d": return date.getDate(); 48 case "D": return dateUtil.formatNum(date.getDate()); 49 case "h": return date.getHours(); 50 case "H": return dateUtil.formatNum(date.getHours()); 51 case "f": return date.getMinutes(); 52 case "F": return dateUtil.formatNum(date.getMinutes()); 53 case "s": return date.getSeconds(); 54 case "S": return dateUtil.formatNum(date.getSeconds()); 55 } 56 }); 57 }, 58 // @description 是否为为日期对象,该方法可能有坑,使用须要慎重 59 // @param year {num} 日期对象 60 // @return {boolean} 返回值 61 isDate: function (d) { 62 if ((typeof d == 'object') && (d instanceof Date)) return true; 63 return false; 64 }, 65 // @description 是否为闰年 66 // @param year {num} 多是年份或者为一个date时间 67 // @return {boolean} 返回值 68 isLeapYear: function (year) { 69 //传入为时间格式须要处理 70 if (dateUtil.isDate(year)) year = year.getFullYear() 71 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true; 72 else return false; 73 }, 74 75 // @description 获取一个月份的天数 76 // @param year {num} 多是年份或者为一个date时间 77 // @param year {num} 月份 78 // @return {num} 返回天数 79 getDaysOfMonth: function (year, month) { 80 if (dateUtil.isDate(year)) { 81 month = year.getMonth(); //注意此处月份要加1,因此咱们要减一 82 year = year.getFullYear(); 83 } 84 return [31, dateUtil.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 85 }, 86 87 // @description 获取一个月份1号是星期几,注意此时的月份传入时须要自主减一 88 // @param year {num} 多是年份或者为一个date时间 89 // @param year {num} 月份 90 // @return {num} 当月一号为星期几0-6 91 getBeginDayOfMouth: function (year, month) { 92 if ((typeof year == 'object') && (year instanceof Date)) { 93 month = year.getMonth(); //注意此处月份要加1 94 year = year.getFullYear(); 95 } 96 var d = new Date(year, month, 1); 97 return d.getDay(); 98 } 99 };
既然是日期,必定会有日期项目的操做,咱们这里须要提供一个接口将某一项交给用户操做
这个接口自己不是很难,比较烦的一个时期,就是这里传入的月份是否应该加1的问题
好比咱们操做的明明是4月却要这样写2014-3-20,这个事情比较烦,因此建议传日期对象算了
//操做每个日期 handleDay: function (dateStr, fn) { if (dateUtil.isDate(dateStr)) dateStr = dateUtil.format(dateStr, 'Y-m-d'); var el = this.root.find('[data-date="' + dateStr + '"]'); if (typeof fn == 'function') fn(el, dateUtil.parse(dateStr, 'y-m-d'), this); } var c = new Calendar({ }); c.handleDay(new Date(), function (el, date, calendar) { el.html('今天'); });
这个的好处是什么呢,如果咱们有一个需求须要修改某一个星期,或者几个连续工做日的属性即可以如此操做,可是须要操做每一个dom结构彷佛有点不舒服
好比咱们如今要去这个月周三高亮显示,这个时候咱们的日历还须要提供一个接口,让外面能够对本身作遍历操做
eachDay: function (fn) { var els = this.root.find('[data-date]'); if (typeof fn == 'function') fn(els); } c.eachDay(function (els) { $.each(els, function (i, el) { el = $(el); el.html(el.html() + '号'); }); }); c.handleDay(new Date(), function (el, date, calendar) { el.html('今天'); });
这里依旧有一个问题:DOM操做太多了,这个方案有问题,因此咱们还得优化
待续......
今天太晚了,咱们下次继续