插件封装前奏【日期选择器分析】

分析在注释中,路过者可以点拨一二
插件不是自己写的,作者很棒,而且后期好像更新了插件,先分析这个第一版


; (function (undefined) {
	var _global;
	//工具函数
	//配置合并
	function extend(def, opt, override) {
		// for in  遍历对象的属性
		for (var k in opt) {

			// Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
			// https://www.cnblogs.com/weiqinl/p/8683207.html
			// 判断对象的k属性是否为自身属性  也就是判断属性是否是传参过来的,将是传入过来的对象属性赋值给def
			// def是传过来的空对象 ,最后一个override没有实际作用,要么就是是否检查,为true就是不检查

			if (opt.hasOwnProperty(k) && (!def.hasOwnProperty(k) || override)) {
				def[k] = opt[k]
			}
		}
		return def;
	}
	//日期格式化
	function concatDate(y, m, d) {
		var symbol = '-';
		if (m) {
			//判断月份是否个位数,是个位数就前面加0
			m = (m.toString())[1] ? m : '0' + m;
		}
		if (d) {
			//判断日是否个位数,是个位数就前面加0
			d = (d.toString())[1] ? d : '0' + d;
		}

		return y + (m ? symbol + m : '') + (d ? symbol + d : '');
	}
	//得到时间戳
	function getTimeStamp(d) {

		var date = new Date(d);

		if (isNaN(date.getTime())) {
			console.error(d + ' is invalid date');
			return '';
		}

		return date.getTime();
	}

	//polyfill  不知道这个放这里什么作用
	if (!Array.isArray) {
		Array.isArray = function (arg) {
			return Object.prototype.toString.call(arg) === '[object Array]';
		};
	}

	//过滤非日期,格式化日期
	//arr 为时间数组
	function filterDate(arr) {

		// 判断传入的是否为数组,不是返回空数组
		if(!Array.isArray(arr)) {
			return [];
		}

		arr = arr || [];  //是不是多余?

		var dateArr = [];

		// 遍历传入的时间数组,数组中的每个值都是一个时间
		for (var i = 0; i < arr.length; i++) {

			var item = arr[i];
			// 将时间字符串转换为标准时间格式
			// Mon Aug 20 2018 00:00:00 GMT+0800 (中国标准时间)
			var date = new Date(item);

			if (isNaN(date.getTime())) {
				console.error(item + ' is invalid date')
			} else {
				var y = date.getFullYear();
				var m = date.getMonth();
				var d = date.getDate();
				var dateStr = concatDate(y, m + 1, d);
				//console.log(typeof dateStr)
				// 没太明白,是否意思是将字符串日志转换为了常规日期?
				// 但是concatDate后,不又把日期拼接为字符串了吗,要么就是起到过滤非日期的功能
				dateArr.push(dateStr);
			}
		}

		return dateArr;
	}
	

	function Schedule(opt) {
		var def = {},
			opt = extend(def, opt, true),

			// 判断有没有传入自定义日历开始时间,如果没有就设置为当前时间
			curDate = opt.date ? new Date(opt.date) : new Date(),

			// 传入的是灰色日期数组(禁用的日期)  过滤非日期,得到的是一个日期字符串数组,格式为2011-01-22
			disabledDate = opt.disabledDate ? filterDate(opt.disabledDate) : [],

			// 功能同上 (选中的日期)
			selectedDate = opt.selectedDate ? filterDate(opt.selectedDate) : [],

			//传入(禁用此日期之前) 得到一个时间戳
			disabledBefore = opt.disabledBefore ? getTimeStamp(opt.disabledBefore) : '',
			//同上,传入的是(禁用此日期之后)
			disabledAfter = opt.disabledAfter ? getTimeStamp(opt.disabledAfter) : '',

			//传入一个布尔值,默认为true
			showToday = opt.showToday,

			// 获取传入日期的年月日,或者是当前日期的年月日,有两个变量重复了,继续看
			year = curDate.getFullYear(),
			month = curDate.getMonth(),
			currentYear = curDate.getFullYear(),
			currentMonth = curDate.getMonth(),
			currentDay = curDate.getDate(),
			activeDate = '',

			//el为传入的前台dom节点
			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;
					case 'todayBtn':
						_this.renderToday();
						break;
					default:
						break;
				};

				//判断点击的dom是否包含currentDate属性,没看到有什么意义
				if (e.target.className.indexOf('currentDate') > -1) {
					activeDate = e.target.title;
					opt.clickCb && opt.clickCb(activeDate);
					render();
				}
			}, false)
		}



		//一系列的dom写入操作
		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"></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>';
			var todayBtn = '<div id="todayBtn" class="today">今天</div>'

			// 写入到el dom中
			el.innerHTML = scheduleHd + scheduleWeek + scheduleBd + (showToday ? todayBtn : '');
			bindEvent(); //其实可以把el的监听事件直接搬过来。
			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++) {

				var nowDate = concatDate(year, month + 1, (i + 1 - startWeek));
				var nowTimestamp = new Date(nowDate).getTime();
				var isDisbale = disabledDate.indexOf(nowDate) > -1;
				var isSelected = selectedDate.indexOf(nowDate) > -1;

				if (i < startWeek) {

					eleTemp.push('<li class="other-month"><span class="dayStyle">' + (lastMonthDay - startWeek + 1 + i) + '</span></li>')
				} else if (i < (startWeek + fullDay)) {

					var addClass = '';
					if (isDisbale) {
						addClass = 'disabled'
					} else {
						isSelected && (addClass = 'selected-style');
						activeDate == nowDate && (addClass = 'active-style');
						concatDate(currentYear, currentMonth + 1, currentDay) == nowDate && (addClass = 'today-flag');
					}

					if (disabledBefore && nowTimestamp < disabledBefore) {
						addClass = 'disabled'
					}
					if (disabledAfter && nowTimestamp > disabledAfter) {
						addClass = 'disabled'
					}

					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 = concatDate(year, month + 1);
		};


		// 切换上下月份和上下年份的事件的方法
		this.nextMonthFun = function () {
			if (month + 1 > 11) {
				year += 1;
				month = 0;
			} else {
				month += 1;
			}
			render();
			opt.nextMonthCb && opt.nextMonthCb(year, month + 1);
		};
		this.nextYearFun = function () {
			year += 1;
			render();
			opt.nextYeayCb && opt.nextYeayCb(year, month + 1);
		};
		this.prevMonthFun = function () {
			if (month - 1 < 0) {
				year -= 1;
				month = 11;
			} else {
				month -= 1;
			}
			render();
			opt.prevMonthCb && opt.prevMonthCb(year, month + 1);
		};
		this.prevYearFun = function () {
			year -= 1;
			render();
			opt.prevYearCb && opt.prevYearCb(year, month + 1);
		}
		this.renderToday = function () {
			if (year === currentYear && month === currentMonth) {
				return;
			}

			year = currentYear;
			month = currentMonth;
			render();
		}


		init();  //do do do
	}




	//将插件暴露给全局对象  常规的script引入的话,直接returun出去,或者用window传出也是一样
	_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);
	}

}());

前端

	<div id='schedule-box' class="boxshaw">

	</div>
	<div>
		<h3 id='h3Ele'></h3>
	</div>
<script>
	var mySchedule = new Schedule({
		el: '#schedule-box',	//容器元素
		date: '2018-09-20',		//当前日期
		disabledBefore: '2018-07-10',	//禁用此日期之前
		disabledAfter: '2018-11-15',	//禁用此日期之后
		disabledDate: ['2018-8-20', '2018-8-2', '2018-8-23'],	//禁用的日期
		selectedDate: ['2018-10-21', '2018-10-22', '2018-10-23'],	//选中的日期
		showToday: true,	//回到今天
		clickCb: function (date) {
			document.querySelector('#h3Ele').innerHTML = '日期:' + date
		},
		nextMonthCb: function (currentYear, currentMonth) {
			console.log('currentYear:' + currentYear, 'currentMonth:' + currentMonth)
		},
		nextYeayCb: function (currentYear, currentMonth) {
			console.log('currentYear:' + currentYear, 'currentMonth:' + currentMonth)
		},
		prevMonthCb: function (currentYear, currentMonth) {
			console.log('currentYear:' + currentYear, 'currentMonth:' + currentMonth)
		},
		prevYearCb: function (currentYear, currentMonth) {
			console.log('currentYear:' + currentYear, 'currentMonth:' + currentMonth)
		}
	});
</script>
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值