html文件:

<!DOCTYPE html>
<html>
<head lang="en">
	<meta charset='utf-8'/>
	<title>lesson1_自定义日历插件</title>
	<link rel="stylesheet" type="text/css" href="schedule/schedule.css">
	<link rel="stylesheet" href="https://at.alicdn.com/t/font_234130_nem7eskcrkpdgqfr.css">
	<style>
		#calendar{
			width: 400px;
			margin: 50px auto;
			padding: 30px;
		}
	</style>
</head>
<body>
<!-- 
	一、引入日历插件的步骤
		1.引入schedule插件的css文件,记得要放在页面的起始位置
			(是因为css文件中有对页面进行初始化的代码,如果不需要可以手动删除)
		2.引入alicdn字体文件,设置左右切换按钮的样式
			 如果不需要,可以自定义按钮样式
			 <link rel="stylesheet" href="https://at.alicdn.com/t/font_234130_nem7eskcrkpdgqfr.css">
		3.引入schedule插件的js文件

	二、使用日历插件的步骤
		1.在html中设置一个div,作为日历插件的容器
		<div id='xxx' class='boxshaw'></div>
		(1)其中id属性是非必要属性,只是为了在js脚本中选中元素用的
		(2)其中class属性是boxshaw,是必要属性,如果不写会缺失日历的阴影效果

		2.对日历插件进行实例化操作
		在脚本中使用var xxx = new Schedule(JSON);方法对日历插件进行实例化
		参数为JSON格式

		3.对schedule的JSON格式参数进行设置
		(1)el:选中日历插件的承载容器,必要字段,一般习惯放在首位
			 var mySchedule = new Schedule({
				el:'#id名',
				...
			 });
		(2)clickCb:日期的点击回调函数,必要字段,一般习惯放在el字段的后面
			本回调函数提供了三个参数,分别代表点击日期的年月日
			年月type是Number数字类型,日期类型为String字符串类型
			var mySchedule = new Schedule({
				...
				clickCb:function (year, month, day){...}
			});
		(3)nextMonthCb:切换到下个月的点击回调函数,非必要属性
			本回调函数提供了三个参数,分别代表点击日期的年月日
			年月type是Number数字类型,日期类型为String字符串类型
			var mySchedule = new Schedule({
				...
				nextMonthCb:function (year, month, day){...}
			});
		(4)nextYearCb: 切换到下个年点击回调函数,非必要属性
			本回调函数有三个参数,分别代表点击日期选项的年月日,
			年月类型是数字,日期类型为字符串
			var mySchedule = new Schedule({
				...
				nextYearCb: function(year, month, day){}
				...
			});
		(5)prevMonthCb: 切换到下个月点击回调函数,非必要属性
			本回调函数有三个参数,分别代表点击日期选项的年月日,
			年月类型是数字,日期类型为字符串
			var mySchedule = new Schedule({
				...
				prevMonthCb: function(year, month, day){}
				...
			});
		(6)prevYearCb: 切换到下个月点击回调函数,非必要属性
			本回调函数有三个参数,分别代表点击日期选项的年月日,
			年月类型是数字,日期类型为字符串
			var mySchedule = new Schedule({
				...
				prevYearCb: function(year, month, day){}
				...
			});
 -->
<div id="calendar" class="boxshaw"></div>
<script src='schedule/schedule.js'></script>
<script>
	var calendar = new Schedule({
		el:'#calendar',
		clickCb:function (year, month, day){
			console.log(year+'-'+month+'-'+day);
		},
		nextMonthCb:function (year, month, day){
			console.log(year);
			console.log(typeof year);
			console.log(month);
			console.log(typeof month);
			console.log(day);
			console.log(typeof day);
		}
	});

</script>
</body>
</html>

css文件:

*{
	margin: 0;
	padding: 0;
}
ul{
	list-style: none;
}
.schedule-hd{
	display: flex;
	justify-content: space-between;
	padding: 0 15px;
}
.today{
	flex: 1;
	text-align: center;
}
.ul-box{
	overflow: hidden;
}
.ul-box > li{
	float: left;
	width: 14.28%;
	text-align: center;
	padding: 5px 0;
}
.other-month{
	color: #999999;
}
.current-month{
	color: #333333;
}
.today-style{
	border-radius: 50%;
	background: #58d321;
}
.arrow{
	cursor: pointer;
}
.dayStyle{
	display: inline-block;
	width: 35px;
	height: 35px;
	border-radius: 50%;
	text-align: center;
	line-height: 35px;
	cursor: pointer;
}
.current-month > .dayStyle:hover{
	background: #00BDFF;
	color: #ffffff;
}
.today-flag{
	background: #00C2B1;
	color: #fff;
}
.boxshaw{
	box-shadow: 2px 2px 15px 2px #e3e3e3;
}
.selected-style {
	background: #00BDFF;
	color: #ffffff;
}

js文件:

(function (undefined) {
	var _global;
	//工具函数
	//配置合并
	function extend (def,opt,override) {
		for(var k in opt){
			if(opt.hasOwnProperty(k) && (!def.hasOwnProperty(k) || override)){
				def[k] = opt[k]
			}
		}
		return def;
	}
	//日期格式化
	function formartDate (y,m,d,symbol) {
		symbol = symbol || '-';
		m = (m.toString())[1] ? m : '0'+m;
		d = (d.toString())[1] ? d : '0'+d;
		return y+symbol+m+symbol+d
	}

	function Schedule (opt) {
		var def = {},
			opt = extend(def,opt,true),
			curDate = opt.date ? new Date(opt.date) : new Date(),
			year = curDate.getFullYear(),
			month = curDate.getMonth(),
			day = curDate.getDate(),	
			currentYear = curDate.getFullYear(),
			currentMonth = curDate.getMonth(),
			currentDay = curDate.getDate(),
			selectedDate = '',
			el = document.querySelector(opt.el) || document.querySelector('body'),
			_this = this;
		var bindEvent = function (){
			el.addEventListener('click',function(e){
				switch (e.target.id) {
					case 'nextMonth': 
						_this.nextMonthFun();
						break;
					case 'nextYear': 
						_this.nextYearFun();
						break;
					case 'prevMonth': 
						_this.prevMonthFun();
						break;
					case 'prevYear': 
						_this.prevYearFun();
						break;
					default:
						break;
				};
				if(e.target.className.indexOf('currentDate') > -1){
					opt.clickCb && opt.clickCb(year, month+1, e.target.innerHTML);
					selectedDate = e.target.title;
					day = e.target.innerHTML;
					render();
				}
			},false)
		}
		var init = function () {
			var scheduleHd = '<div class="schedule-hd">'+
								'<div>'+
									'<span class="arrow icon iconfont icon-116leftarrowheads" id="prevYear" ></span>'+
									'<span class="arrow icon iconfont icon-112leftarrowhead" id="prevMonth"></span>'+
								'</div>'+
								'<div class="today">'+formartDate(year,month+1,day,'-')+'</div>'+
								'<div>'+
									'<span class="arrow icon iconfont icon-111arrowheadright" id="nextMonth"></span>'+
									'<span class="arrow icon iconfont icon-115rightarrowheads" id="nextYear"></span>'+
								'</div>'+
							'</div>'
			var scheduleWeek = '<ul class="week-ul ul-box">'+
									'<li>日</li>'+
									'<li>一</li>'+
									'<li>二</li>'+
									'<li>三</li>'+
									'<li>四</li>'+
									'<li>五</li>'+
									'<li>六</li>'+
								'</ul>'
			var scheduleBd = '<ul class="schedule-bd ul-box" ></ul>'; 
			el.innerHTML = scheduleHd + scheduleWeek + scheduleBd;
			bindEvent();
			render();
		}
		var render = function () {
			var fullDay = new Date(year,month+1,0).getDate(), //当月总天数
				startWeek = new Date(year,month,1).getDay(), //当月第一天是周几
				total = (fullDay+startWeek)%7 == 0 ? (fullDay+startWeek) : fullDay+startWeek+(7-(fullDay+startWeek)%7),//元素总个数
				lastMonthDay = new Date(year,month,0).getDate(), //上月最后一天
				eleTemp = [];
			for(var i = 0; i < total; i++){
				if(i<startWeek){
					eleTemp.push('<li class="other-month"><span class="dayStyle">'+(lastMonthDay-startWeek+1+i)+'</span></li>')
				}else if(i<(startWeek+fullDay)){
					var nowDate = formartDate(year,month+1,(i+1-startWeek),'-');
					var addClass = '';
					selectedDate == nowDate && (addClass = 'selected-style');
					formartDate(currentYear,currentMonth+1,currentDay,'-') == nowDate && (addClass = 'today-flag');
					eleTemp.push('<li class="current-month" ><span title='+nowDate+' class="currentDate dayStyle '+addClass+'">'+(i+1-startWeek)+'</span></li>')
				}else{
					eleTemp.push('<li class="other-month"><span class="dayStyle">'+(i+1-(startWeek+fullDay))+'</span></li>')
				}
			}
			el.querySelector('.schedule-bd').innerHTML = eleTemp.join('');
			el.querySelector('.today').innerHTML = formartDate(year,month+1,day,'-');
		};
		this.nextMonthFun = function () {
			if(month+1 > 11){
				year += 1;
				month = 0;
			}else{
				month += 1;
			}
			render();
			opt.nextMonthCb && opt.nextMonthCb(year,month+1,day);
		},
		this.nextYearFun = function () {
			year += 1;
			render();
			opt.nextYeayCb && opt.nextYeayCb(year,month+1,day);
		},
		this.prevMonthFun = function () {
			if(month-1 < 0){
				year -= 1;
				month = 11;
			}else{
				month -= 1;
			}
			render();
			opt.prevMonthCb && opt.prevMonthCb(year,month+1,day);
		},
		this.prevYearFun = function () {
			year -= 1;
			render();
			opt.prevYearCb && opt.prevYearCb(year,month+1,day);
		}
		init();
	}
	//将插件暴露给全局对象
	_global = (function(){return this || (0,eval)('this')}());
	if(typeof module !== 'undefined' && module.exports){
		module.exports = Schedule;
	}else if (typeof define === "function" && define.amd){
		define(function () {
			return Schedule;
		})
	}else {
		!('Schedule' in _global) && (_global.Schedule = Schedule);
	}

}());