日期插件,input点击日期选择

585 阅读7分钟

一个简单的日期插件,通过对input定义相对应的id,即可实现点击input出现日期选择,选择后展示在input框中

html代码展示

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>日期插件</title>
		<link type="text/css" rel="stylesheet" href="data-pickerv20.css">
		<style type="text/css">
			* {
				margin: 0;
				padding: 0;
				list-style: none;
			}

			body {
				/* background-color: #E3E3E3; */
				font-size: 14px;
				color: #333;
				font-family: '微软雅黑'
			}

			.main {
				width: 202px;
				margin: 0 auto;
				background: #fff;
				padding: 50px
			}

			#date1,
			.time {
				display: inline-block;
				width: 200px;
				height: 30px;
				border: 1px solid #ccc;
				vertical-align: middle;
				margin: 20px 5px;
				line-height: 30px
			}
		</style>
	</head>
	<body>
		<!-- <div class="main"> -->
			<input type="text" id="date1" placeholder="请选择日期"/>
		<!-- </div> -->
	</body>
	<script type="text/javascript" src="data-pickerv20.js"></script>
	<script type="text/javascript">
		var picker1 = new Datepicker({
			elemName: 'date1',
			format: 'YYYY-MM-DD',
			min: '1900-01-01 00:00:00',
			callBack: function(a, b) {
				console.log(a, b)
			}
		});
	</script>
</html>

通过设置input的id和elemName相对应实现input日期选

JS代码展示

var Datepicker = (function() {
	// -- 核心工具方法 -- //
	var Utils = {};
	Utils.on = function(elem, even, target, fn) { //--事件监听器
		if (typeof target === 'string') {
			elem.addEventListener(even, function(e) {
				if (e.target.tagName === target.toLocaleUpperCase()) {
					fn.call(e.target, e);
					e.stopPropagation()
				}
			}, false);
		} else {
			fn = target;
			elem.addEventListener(even, function(e) {
				fn.call(this, e);
				e.stopPropagation()
			}, false);
		}
		return Utils;
	};

	Utils.extend = function(options, newoptions, deep) { // 扩展覆盖属性
		for (var key in newoptions) {
			if (deep && (isPlainObject(newoptions[key]) || Array.isArray(newoptions[key]))) {
				if (isPlainObject(newoptions[key]) && !isPlainObject(options[key]))
					options[key] = {}
				if (Array.isArray(newoptions[key]) && !Array.isArray(options[key]))
					options[key] = []
				Utils.extend(options[key], source[key], deep)
			} else if (newoptions[key] !== undefined) options[key] = newoptions[key]
		}

		function isPlainObject(obj) {
			try {
				if (obj.constructor && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) return false;
			} catch (e) {
				return false;
			}
			return true;
		}
	}

	Utils.isShow = function(dom, bln) { // 显示隐藏
		dom.style.display = bln ? 'block' : 'none';
	}

	Utils.format = function(time, format) { // 时间戳转换指定format格式
		var oDate = new Date(time)
		return format.replace(/YYYY|MM|DD|hh|mm|ss/g, function(str, index) {
			var val = 0;
			if (str === 'YYYY') {
				val = oDate.getFullYear();
			} else if (str === 'MM') {
				val = oDate.getMonth() + 1;
			} else if (str === 'DD') {
				val = oDate.getDate();
			} else if (str === 'hh') {
				val = oDate.getHours();
			} else if (str === 'mm') {
				val = oDate.getMinutes();
			} else if (str === 'ss') {
				val = oDate.getSeconds();
			}
			return Utils.repair(val);
		});
	}

	Utils.parse = function(type, ops) {
		if (type === 1) { // 字符串转ymd
			var ymd = ops.value.match(/\d+/g);
			var aYmd = [];
			for (var i = 0; i < ops.aYmdIndex.length; i++) {
				aYmd.push(ymd[ops.aYmdIndex[i]]);
			}
			return aYmd;
		} else if (type === 2) { // 当前时间转ymd
			ops.value = Utils.format(ops.time, ops.format);
			return Utils.parse(1, ops);
		} else if (type === 3) { // ymd转时间
			// var _t = +new Date(ops.aYmd[0]?ops.aYmd[0]:1970, ops.aYmd[1]?ops.aYmd[1]:0, ops.aYmd[2]?ops.aYmd[2]:0, ops.aYmd[3]?ops.aYmd[3]:0, ops.aYmd[4]?ops.aYmd[4]:0, ops.aYmd[5]?ops.aYmd[5]:0);
			// return {'value':Utils.format(_t, ops.format), 'time':_t} 
		}
	};

	Utils.repair = function(num) { // 补0
		return (num < 10 ? '0' : '') + num;
	}

	Utils.each = function(list, fn) {
		var i = 0,
			len = list.length;
		for (; i < len; i++) {
			if (fn(i, list[i]) === false) break;
		};
	}

	Utils.check = function(_ymd, _minArr, _maxArr) {
		return maketime(_ymd, _minArr) < maketime(_minArr) || maketime(_ymd, _maxArr) > maketime(_maxArr)

		function maketime(arr, _arr) {
			if (!_arr) _arr = [1970, 1, 1, 0, 0, 0];
			return +new Date(n(arr[0], _arr[0]), n(arr[1], _arr[1]) - 1, n(arr[2], _arr[2]), n(arr[3], _arr[3]), n(arr[4],
				_arr[4]), n(arr[5], _arr[5]));
		}

		function n(a, b) {
			return a === undefined ? (b === undefined ? 0 : b) : a;
		}
	}

	Utils.scroll = function(isLeft) {
		var type = isLeft ? 'scrollLeft' : 'scrollTop';
		return document.body[type] | document.documentElement[type];
	};
	// -- 组件对象 -- //
	var dpdate = function(options) {
		var that = this;
		this.config = {
			format: 'YYYY-MM-DD', // 日期格式
			min: '1970-01-01 00:00:00', // 最小日期
			max: '2099-12-12 23:59:59', // 最大日期	
			eventtype: '',
			elemName: '',
			hasTime: true, // 显示使用时间组件
			hasClear: true, // 显示清空按钮
			hasToday: true, // 显示今天按钮
			hasConfirm: true, // 显示确认按钮
			fixed: false, // 是否fixed浮动
			callBack: null // 选时间回调
		};
		Utils.extend(this.config, options);
		this.config.min = this.parse(this.config.min, 'YYYY-MM-DD') + ' 00:00:00'
		this.config.max = this.parse(this.config.max, 'YYYY-MM-DD') + ' 23:59:59'
		this.elem = document.getElementById(this.config.elemName)
		if (!this.elem) {
			throw new Error('ID选择器找不到元素');
		}
		var valueType = /textarea|input/.test(this.elem.tagName.toLocaleLowerCase()) ? 'value' : 'innerHTML';
		this.getExg(); // 获取value合法性正则
		this.check(this.elem[valueType]); // 检查当前输入框的值 重置ymd
		Utils.on(this.elem, this.eventtype || 'click', function(e) {
			that.check(that.elem[valueType]);
			DateView.redraw(that, valueType);
		})
	};

	dpdate.prototype.setMinScope = function(str, tar) {
		this.config.min = str;
		if (tar && typeof str === 'number') {
			this.config.min = Utils.format(str + tar * 86400000, this.config.format)
		}
	}

	dpdate.prototype.setMaxScope = function(str, tar) {
		this.config.max = str;
		if (tar && typeof str === 'number') {
			this.config.max = Utils.format(str + tar * 86400000, this.config.format)
		}
	}

	dpdate.prototype.getExg = function() { // 制作验证正则 对应年月日位置
		this.aYmdIndex = new Array(6);
		var that = this;
		var i = 0;
		var reg = this.config.format.replace(/YYYY|MM|DD|hh|mm|ss/g, function(str, index) {
			var exg = '';
			if (str === 'YYYY') {
				exg += '((19|20)\\\d{2})';
				that.aYmdIndex[0] = i;
			} else if (str === 'MM') {
				exg += '(0?[1-9]|1[0-2])'
				that.aYmdIndex[1] = i;
			} else if (str === 'DD') {
				exg += '(0?[1-9]|[1-3][0-9])'
				that.aYmdIndex[2] = i;
			} else if (str === 'hh') {
				exg += '\\\d{2}'
				that.aYmdIndex[3] = i;
			} else if (str === 'mm') {
				exg += '\\\d{2}'
				that.aYmdIndex[4] = i;
			} else if (str === 'ss') {
				exg += '\\\d{2}'
				that.aYmdIndex[5] = i;
			}
			i++;
			return exg;
		});
		this.reg = new RegExp('^' + reg + '$')
	}

	dpdate.prototype.check = function(_value) { // 检查value合法性,转化时间ymd
		this.aYmd = this.reg.test(_value) ? Utils.parse(1, {
				aYmdIndex: this.aYmdIndex,
				value: _value
			}) :
			Utils.parse(2, {
				aYmdIndex: this.aYmdIndex,
				value: _value,
				format: 'YYYY-MM-DD',
				time: +new Date
			})
	}

	dpdate.prototype.parse = function(time, format) {
		if (typeof time === 'string') return time;
		return Utils.format(time < 86400000 ? +new Date + time * 86400000 : time, format || 'YYYY-MM-DD')
	}

	// -- 日历视图对象 -- //
	var DateView = {
		dom: null,
		firstRedraw: false,
		_init: function() { // 骨架
			this.dom = document.createElement('div');
			this.dom.className = 'datepicker-sh';
			this.dom.innerHTML = '<div class="dp_top">' +
				'<div class="dp_box box1" id="box1">' +
				'<a href="javascript:;" class="dp_prevX"></a>' +
				'<div class="dp_year">' +
				'<span class="dp_year_val"><span class="val">2015</span>年</span>' +
				'<span class="dp_down dp_year_next"></span>' +
				'<div class="dp_year_listBox">' +
				'<a href="javascript:;" class="dp_prevY"></a>' +
				'<ul class="dp_year_list"></ul>' +
				'<a href="javascript:;" class="dp_nextY"></a>' +
				'</div>' +
				'</div>' +
				'<a href="javascript:;" class="dp_nextX"></a>' +
				'</div>' +
				'<div class="dp_box box2" id="box2">' +
				'<a href="javascript:;" class="dp_prevX"></a>' +
				'<div class="dp_month">' +
				'<span class="dp_month_val"><span class="val">1</span>月</span>' +
				'<span class="dp_down dp_month_next"></span>' +
				'<div class="dp_month_listBox"><ul class="dp_month_list"></ul></div>' +
				'</div>' +
				'<a href="javascript:;" class="dp_nextX"></a>' +
				'</div>' +
				'</div>' +
				'<div class="db_body">' +
				'<ul class="db_li db_week"><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul>' +
				'<ul class="db_li db_day"></ul>' +
				'</div>' +
				'<div class="dp_bottom">' +
				'<div class="dp_time">' +
				'<span class="dp_timefont">时间</span>' +
				'<ul class="dp_time_box"><li><input type="text" value="00" class="hh">:</li><li><input type="text" value="00" class="mm">:</li><li><input type="text" value="00" class="ss"></li></ul>' +
				'</div>' +
				'<div class="dp_btns"><a href="javascript:;" class="dp_btn clear">清空</a><a href="javascript:;" class="dp_btn dp_cl_r today">今天</a><a href="javascript:;" class="dp_btn dp_cl_r ok">确认</a></div>' +
				'<div class="dp_timebox dp_60"><div class="dp_head"><span class="db_title">秒</span><i class="db_close">×</i></div><ul class="db_time_list"></ul></div>' +
				'</div>';
			this._findDom(); // 找元素
			this._events(); // 事件委托
		},
		_findDom: function() {
			var dom = this.dom;
			var box1 = getDomByCls(dom, 'box1');
			var box2 = getDomByCls(dom, 'box2');
			this.doms = {
				yearBtn: getDomByCls(box1, 'dp_year'), //年按钮
				yearLeft: getDomByCls(box1, 'dp_prevX'), //上一年
				yearRight: getDomByCls(box1, 'dp_nextX'), //下一年
				yearInput: getDomByCls(box1, 'val'), //年input
				yearListBox: getDomByCls(box1, 'dp_year_listBox'), //年列表盒子
				yearTop: getDomByCls(box1, 'dp_prevY'), //年上一页列表
				yearBottom: getDomByCls(box1, 'dp_nextY'), //年下一页列表
				yearList: getDomByCls(box1, 'dp_year_list'), //年列表
				monthBtn: getDomByCls(box2, 'dp_month'), //月按钮
				monthLeft: getDomByCls(box2, 'dp_prevX'), //上一月
				monthRight: getDomByCls(box2, 'dp_nextX'), //下一月
				monthInput: getDomByCls(box2, 'val'), //月input
				monthListBox: getDomByCls(box2, 'dp_month_listBox'), //月列表盒子
				monthList: getDomByCls(box2, 'dp_month_list'), //月列表
				dayList: getDomByCls(dom, 'db_day'), //日列表
				timeBox: getDomByCls(dom, 'dp_time'), //时间组件
				inputH: getDomByCls(dom, 'hh'), //时input
				inputM: getDomByCls(dom, 'mm'), //分input
				inputS: getDomByCls(dom, 'ss'), //秒input
				btnBox: getDomByCls(dom, 'dp_btns'), //按钮组件
				clearBtn: getDomByCls(dom, 'clear'), //清空按钮
				todayBtn: getDomByCls(dom, 'today'), //今天按钮
				okBtn: getDomByCls(dom, 'ok'), //确认按钮
				timeListBox: getDomByCls(dom, 'dp_timebox'), //时间列表盒
				timeListTitle: getDomByCls(dom, 'db_title'), //时间列表标题
				timeListClose: getDomByCls(dom, 'db_close'), //时间列表关闭
				timeList: getDomByCls(dom, 'db_time_list') //时间列表
			}

			function getDomByCls(dom, name) {
				return dom.getElementsByClassName(name)[0];
			}
		},
		redraw: function(_obj, _valueType) { // 更新骨架内容
			this.dateObj = _obj;
			var _aYmd = _obj.aYmd,
				_config = _obj.config,
				_elem = _obj.elem;
			if (!this.firstRedraw) {
				this.firstRedraw = true;
				document.body.appendChild(this.dom)
			}
			// 引用更新对象
			this.aYmd = _aYmd;
			this.config = _config;
			this.elem = _elem;
			this.valueType = _valueType;
			this.maxArr = _config.max.match(/\d+/g);
			this.minArr = _config.min.match(/\d+/g);
			// 记录当前选择时间
			this.Y = _aYmd[0] ? parseInt(_aYmd[0]) : 1970;
			this.M = _aYmd[1] ? parseInt(_aYmd[1]) : 1;
			this.D = _aYmd[2] ? parseInt(_aYmd[2]) : 1;
			this.h = _aYmd[3] ? parseInt(_aYmd[3]) : 0;
			this.m = _aYmd[4] ? parseInt(_aYmd[4]) : 0;
			this.s = _aYmd[5] ? parseInt(_aYmd[5]) : 0;
			this.doms.yearInput.innerHTML = _aYmd[0];
			this.doms.monthInput.innerHTML = _aYmd[1];
			this._drawDate(this.Y, this.M, this.D);
			Utils.isShow(this.doms.timeBox, _config.hasTime);
			this.doms.inputH.value = _aYmd[3] ? _aYmd[3] : '00';
			this.doms.inputM.value = _aYmd[4] ? _aYmd[4] : '00';
			this.doms.inputS.value = _aYmd[5] ? _aYmd[5] : '00';
			// 显示组件
			Utils.isShow(this.doms.clearBtn, _config.hasClear);
			Utils.isShow(this.doms.todayBtn, _config.hasToday);
			Utils.isShow(this.doms.okBtn, _config.hasConfirm);
			this._close(true)
			// 定位组件
			this._position(_elem, _config.fixed)
		},
		_checkDate: function(_ymd) {
			return Utils.check(_ymd, this.minArr, this.maxArr)
		},
		_checkOk: function() { // 根据范围控制确认按钮可点
			if (this._checkDate([this.Y, this.M, this.D, this.h, this.m, this.s])) {
				this.doms.okBtn.setAttribute('dis', 'yes');
				this.doms.okBtn.className = 'dp_btn dp_cl_r dis'
			} else {
				this.doms.okBtn.setAttribute('dis', '');
				this.doms.okBtn.className = 'dp_btn dp_cl_r ok'
			}
		},
		_events: function() { //绑定事件找元素
			var _this = this,
				yearPage = 0,
				hmsType = '';
			// vm自动 (NO IE8)
			// var year = this.Y;
			// Object.defineProperty(this, "Y", {
			//     get: function(){return year; },
			//     set: function(val){year = val; _this.doms.yearInput.innerHTML=val }
			// })
			// 绑定选年事件(左右 显示列表及点击 更新日历)
			Utils.on(this.doms.yearLeft, 'click', function(e) {
				if (_this._checkDate([_this.Y - 1])) return false
				_this.doms.yearInput.innerHTML = --_this.Y;
				_this._closelayer()._drawDate()._checkOk();
			});
			Utils.on(this.doms.yearRight, 'click', function(e) {
				if (_this._checkDate([_this.Y + 1])) return false
				_this.doms.yearInput.innerHTML = ++_this.Y;
				_this._closelayer()._drawDate()._checkOk();
			});
			Utils.on(this.doms.yearBtn, 'click', function(e) {
				yearPage = 0;
				_this._closelayer()._drawYearList(yearPage);
				Utils.isShow(_this.doms.yearListBox, true);
			});
			Utils.on(this.doms.yearTop, 'click', function(e) {
				_this._drawYearList(--yearPage);
			});
			Utils.on(this.doms.yearBottom, 'click', function(e) {
				_this._drawYearList(++yearPage);
			});
			Utils.on(this.doms.yearList, 'click', 'li', function(e) {
				if (this.getAttribute('dis')) {
					e.stopPropagation()
					return false
				}
				_this.doms.yearInput.innerHTML = _this.Y = parseInt(this.innerHTML);
				_this._closelayer()._drawDate()._checkOk();
			});
			// 绑定选月事件(左右 显示列表及点击 更新日历)
			Utils.on(this.doms.monthLeft, 'click', function(e) {
				if (_this._checkDate([_this.Y, _this.M - 1])) return false
				if (--_this.M < 1) {
					_this.M = 12;
					_this.doms.yearInput.innerHTML = --_this.Y;
				}
				_this.doms.monthInput.innerHTML = _this.M;
				_this._closelayer()._drawDate()._checkOk();
			});
			Utils.on(this.doms.monthRight, 'click', function(e) {
				if (_this._checkDate([_this.Y, _this.M + 1])) return false
				if (++_this.M > 12) {
					_this.M = 1;
					_this.doms.yearInput.innerHTML = ++_this.Y;
				}
				_this.doms.monthInput.innerHTML = _this.M;
				_this._closelayer()._drawDate()._checkOk();
			});
			Utils.on(this.doms.monthBtn, 'click', function(e) {
				_this._closelayer()._drawMonthList();
				Utils.isShow(_this.doms.monthListBox, true);
			});
			Utils.on(this.doms.monthList, 'click', 'li', function(e) {
				if (this.getAttribute('dis')) {
					e.stopPropagation()
					return false
				}
				_this.doms.monthInput.innerHTML = _this.M = parseInt(this.innerHTML);
				_this._closelayer()._drawDate()._checkOk();
			});
			// 选天
			Utils.on(this.doms.dayList, 'click', 'li', function(e) {
				if (this.getAttribute('dis')) {
					e.stopPropagation()
					return false
				}
				_this.M = this.getAttribute('m');
				_this.D = parseInt(this.innerHTML);
				_this.selectDate()._checkOk();
				DateView._close();
			});
			// 绑定时分秒(显示列表及点击)
			Utils.on(this.doms.timeListBox, 'click', function(e) {});
			Utils.on(this.doms.inputH, 'click', function(e) {
				hmsType = 'H';
				_this._drawTimeList(hmsType)
			});
			Utils.on(this.doms.inputM, 'click', function(e) {
				hmsType = 'M';
				_this._drawTimeList(hmsType)
			});
			Utils.on(this.doms.inputS, 'click', function(e) {
				hmsType = 'S';
				_this._drawTimeList(hmsType)
			});
			Utils.on(this.doms.timeListClose, 'click', function(e) {
				_this._closelayer()
			});
			Utils.on(this.doms.timeList, 'click', 'li', function(e) {
				if (this.getAttribute('dis')) {
					e.stopPropagation()
					return false
				}
				var it = parseInt(this.innerHTML);
				_this[hmsType.toLocaleLowerCase()] = it;
				_this.doms['input' + hmsType].value = Utils.repair(it);
				_this._closelayer()._drawDate()._checkOk()
			});
			// 绑定tools按钮
			Utils.on(this.doms.clearBtn, 'click', function(e) {
				_this._close().elem[_this.valueType] = '';
			});
			Utils.on(this.doms.todayBtn, 'click', function(e) {
				var _de = new Date();
				_this.Y = _de.getFullYear();
				_this.M = _de.getMonth() + 1;
				_this.D = _de.getDate();
				_this.selectDate()
			});
			Utils.on(this.doms.okBtn, 'click', function(e) {
				if (this.getAttribute('dis')) {
					e.stopPropagation()
					return false
				}
				_this.selectDate()
			});
			//点击body关闭组件
			Utils.on(document, 'click', function(e) {
				_this._closelayer()
				DateView._close();
			});
			Utils.on(this.dom, 'click', function(e) {
				_this._closelayer()
			});
		},
		_drawYearList: function(p) {
			var _html = '',
				yearRow = 12,
				that = this;
			var _start = yearRow / 2 - 1;
			Utils.each(new Array(yearRow), function(i) {
				var y = that.Y - _start + i + p * yearRow;
				_html += that._checkDate([y]) ? '<li dis="yes">' + y + '</li>' : '<li class="normal">' + y + '</li>';
			})
			this.doms.yearList.innerHTML = _html;
			return this;
		},
		_drawMonthList: function() {
			var _html = '',
				that = this;
			Utils.each(new Array(12), function(i) {
				_html += that._checkDate([that.Y, i + 1]) ? '<li dis="yes">' + Utils.repair(i + 1) + '</li>' :
					'<li class="normal">' + Utils.repair(i + 1) + '</li>'
			})
			this.doms.monthList.innerHTML = _html;
			return this;
		},
		_drawDate: function() {
			var date1, date2, date3, date, dateP, dateT, dayP, _date, _html = '',
				j = 0,
				_time = 0,
				_timeMin, _timeMax;
			date = new Date();
			date1 = new Date(this.Y, this.M - 1, 0);
			date2 = new Date(this.Y, this.M, 0);
			date3 = new Date(this.Y, this.M - 1, 1);
			dateP = date1.getDate(); // 上个月多少天
			dateT = date2.getDate(); // 这个月多少天
			dayP = date3.getDay(); // 1号星期几
			_date = Math.min(dateT, this.D)
			for (var i = 1; i <= 42; i++) {
				if (i <= dayP) {
					_html += this._checkDate([this.Y, this.M - 1, dateP - dayP + i, this.h, this.m, this.s]) ? '<li dis="yes" m="' +
						(this.M - 1) + '">' + (dateP - dayP + i) + '</li>' : '<li class="other" m="' + (this.M - 1) + '">' + (dateP -
							dayP + i) + '</li>';
				} else if (i <= dayP + dateT) {
					var _de = i - dayP;
					var _cls = _de === _date ? 'on' : 'normal';
					_html += this._checkDate([this.Y, this.M, _de, this.h, this.m, this.s]) ? '<li dis="yes" m="' + this.M + '">' +
						(_de) + '</li>' : '<li class="' + _cls + '" m="' + this.M + '">' + (_de) + '</li>';
				} else {
					_html += this._checkDate([this.Y, this.M + 1, j + 1, this.h, this.m, this.s]) ? '<li dis="yes" m="' + (this.M +
						1) + '">' + (++j) + '</li>' : '<li class="other" m="' + (this.M + 1) + '">' + (++j) + '</li>';
				}
			};
			this.doms.dayList.innerHTML = _html;
			return this;
		},
		_drawTimeList: function(type) {
			var kv = {
					'H': {
						n: '时',
						c: 24,
						e: 'h',
						i: 3
					},
					'M': {
						n: '分',
						c: 60,
						e: 'm',
						i: 4
					},
					'S': {
						n: '秒',
						c: 60,
						e: 's',
						i: 5
					}
				},
				_html = '',
				that = this;
			var arr = [that.Y, that.M, that.D, that.h, that.m, that.s];
			Utils.each(new Array(kv[type].c), function(i) {
				var _cls = that[kv[type].e.toLocaleLowerCase()] === i ? 'on' : 'normal';
				arr[kv[type].i] = i;
				_html += that._checkDate(arr) ? '<li dis="yes">' + i + '</li>' : '<li class="' + _cls + '">' + i + '</li>';
			});
			this.doms.timeListBox.className = 'dp_timebox dp_' + kv[type].c;
			this.doms.timeListTitle.innerHTML = kv[type].n;
			this.doms.timeList.innerHTML = _html;
			Utils.isShow(this.doms.timeListBox, true);
		},
		_closelayer: function() {
			Utils.isShow(this.doms.yearListBox, false);
			Utils.isShow(this.doms.monthListBox, false);
			Utils.isShow(this.doms.timeListBox, false);
			return this;
		},
		_position: function(elem, isFixed) {
			this.dom.style.position = isFixed ? 'fixed' : 'absolute'
			var rect = elem.getBoundingClientRect();
			this.dom.style.left = rect.left + (isFixed ? Utils.scroll(true) : 0) + 'px'
			if (rect.bottom + this.dom.offsetHeight < document.documentElement.clientHeight) {
				this.dom.style.top = rect.bottom + (isFixed ? Utils.scroll() : 0) + 'px'
			} else {
				this.dom.style.top = Math.max(rect.top - document.documentElement.clientHeight + (isFixed ? Utils.scroll() : 0),
					0) + 'px';
			}
		},
		selectDate: function() {
			this.aYmd[0] = Utils.repair(this.Y);
			this.aYmd[1] = Utils.repair(this.M);
			this.aYmd[2] = Utils.repair(this.D);
			this.aYmd[3] = Utils.repair(this.h);
			this.aYmd[4] = Utils.repair(this.m);
			this.aYmd[5] = Utils.repair(this.s);
			var time = +new Date(this.Y, this.M - 1, this.D, this.h, this.m, this.s);
			this.elem[this.valueType] = Utils.format(time, this.config.format)
			this.config.callBack(this.elem[this.valueType], time);
			this.dateObj.time = time;
			this.dateObj.value = this.elem[this.valueType];
			this._close();
			return this;
		},
		_close: function(noclose) {
			this.dom.style.display = noclose ? 'block' : 'none';
			return this;
		}
	}
	DateView._init();
	return dpdate
})();

CSS代码展示

.datepicker-sh {
	width: 15pc;
	background: #fff;
	border: 1px solid #ccc;
	font-size: 9pt;
	display: none;
	z-index: 999
}

.datepicker-sh .dp_top {
	height: 26px;
	padding: 5px;
	background: #12a5f8
}

.datepicker-sh .dp_box {
	float: left
}

.datepicker-sh .box1 {
	width: 90pt
}

.datepicker-sh .box2 {
	width: 75pt;
	margin-left: 10px
}

.datepicker-sh .dp_nextX,
.datepicker-sh .dp_prevX {
	width: 20px;
	height: 26px;
	float: left;
	position: relative
}

.datepicker-sh .dp_nextX:hover,
.datepicker-sh .dp_prevX:hover {
	background-color: #12b5f8
}

.datepicker-sh .dp_nextX:after,
.datepicker-sh .dp_prevX:after {
	content: '';
	display: block;
	border: 5px solid transparent;
	position: absolute;
	top: 8px;
	left: 5px
}

.datepicker-sh .dp_prevX:after {
	border-right-color: #fff
}

.datepicker-sh .dp_nextX:after {
	border-left-color: #fff
}

.datepicker-sh .dp_month,
.datepicker-sh .dp_year {
	width: 5pc;
	height: 26px;
	float: left;
	position: relative;
	cursor: pointer
}

.datepicker-sh .dp_year_val {
	position: absolute;
	left: 4px;
	top: 4px;
	color: #fff;
	font-size: 14px
}

.datepicker-sh .dp_down {
	border: 5px solid transparent;
	border-top-color: #fff;
	position: absolute;
	right: 8px;
	top: 9pt
}

.datepicker-sh .dp_month_listBox,
.datepicker-sh .dp_year_listBox {
	width: 90pt;
	position: absolute;
	top: 30px;
	overflow: hidden;
	background: #12a5f8;
	display: none;
	z-index: 1
}

.datepicker-sh .dp_year_listBox {
	left: -25px
}

.datepicker-sh .dp_nextY,
.datepicker-sh .dp_prevY {
	display: block;
	height: 15px;
	overflow: hidden
}

.datepicker-sh .dp_nextY:hover,
.datepicker-sh .dp_prevY:hover {
	background: #12b5f8
}

.datepicker-sh .dp_prevY:after {
	content: '';
	display: block;
	width: 0;
	border: 5px solid transparent;
	border-bottom-color: #fff;
	margin: 0 auto
}

.datepicker-sh .dp_nextY:after {
	content: '';
	display: block;
	width: 0;
	border: 5px solid transparent;
	border-top-color: #fff;
	margin: 5px auto
}

.datepicker-sh .dp_year_list {
	overflow: hidden
}

.datepicker-sh .dp_year_list li {
	width: 60px;
	line-height: 20px;
	float: left;
	text-align: center;
	color: #ccc;
	cursor: default
}

.datepicker-sh .dp_month {
	width: 60px
}

.datepicker-sh .dp_month_val {
	position: absolute;
	left: 9pt;
	top: 5px;
	color: #fff
}

.datepicker-sh .dp_month_listBox {
	width: 75pt;
	left: -15px
}

.datepicker-sh .dp_month_list li {
	width: 50px;
	line-height: 29px;
	float: left;
	text-align: center;
	color: #ccc;
	cursor: default
}

.datepicker-sh .dp_month_list li.normal,
.datepicker-sh .dp_year_list li.normal {
	color: #fff;
	cursor: pointer
}

.datepicker-sh .dp_month_list li.normal:hover,
.datepicker-sh .dp_year_list li.normal:hover {
	background: #12b5f8
}

.datepicker-sh .db_body {
	height: 145px
}

.datepicker-sh .db_li li {
	width: 34px;
	float: left;
	text-align: center;
	color: #eee;
	height: 20px;
	line-height: 20px
}

.datepicker-sh .db_week {
	border-bottom: 1px solid #ccc;
	overflow: hidden;
	padding-left: 1px
}

.datepicker-sh .db_week li {
	color: #12a5f8
}

.datepicker-sh .db_day li.normal {
	color: #00a5f0
}

.datepicker-sh .db_day li.other {
	color: #ccc
}

.datepicker-sh .db_day li.normal:hover,
.datepicker-sh .db_day li.other:hover {
	background: #12b5f8;
	color: #fff;
	cursor: pointer
}

.datepicker-sh .db_day li.on {
	background: #12a5f8;
	color: #fff
}

.datepicker-sh .dp_bottom {
	height: 22px;
	padding: 5px;
	position: relative
}

.datepicker-sh .dp_time {
	display: none !important;
	border: 1px solid #ccc;
	height: 20px;
	line-height: 20px;
	float: left
}

.datepicker-sh .dp_timefont {
	float: left;
	padding: 0 5px
}

.datepicker-sh .dp_cl_r,
.datepicker-sh .dp_time_box {
	float: left;
	border-left: 1px solid #ccc
}

.datepicker-sh .dp_time_box li {
	float: left
}

.datepicker-sh .dp_time_box input {
	width: 20px;
	text-align: center;
	border: none;
	outline: 0;
	cursor: pointer
}

.datepicker-sh .dp_btns {
	border: 1px solid #ccc;
	float: right;
	height: 20px;
	line-height: 20px;
	text-align: center
}

.datepicker-sh .dp_btn {
	width: 25px;
	display: block;
	float: left;
	color: #666;
	text-decoration: none;
	padding: 0 5px
}

.datepicker-sh .dp_btn.dis {
	color: #ccc
}

.datepicker-sh .dp_btn:hover {
	background: #eee
}

.datepicker-sh .dp_timebox {
	width: 75pt;
	height: 75pt;
	background: #fff;
	position: absolute;
	bottom: 25px;
	border: 1px solid #ccc;
	display: none;
	z-index: 1
}

.datepicker-sh .dp_timebox.dp_60 {
	width: 200px;
	height: 140px
}

.datepicker-sh .dp_timebox.dp_24 {
	width: 125px;
	height: 105px
}

.datepicker-sh .dp_head {
	line-height: 20px;
	border-bottom: 1px solid #ccc;
	position: relative;
	text-align: center;
	color: #12a5f8
}

.datepicker-sh .db_close {
	position: absolute;
	right: 5px;
	font-style: normal;
	cursor: pointer
}

.datepicker-sh .dp_timebox ul li {
	float: left;
	width: 20px;
	text-align: center;
	line-height: 20px;
	color: #eee
}

.datepicker-sh .dp_timebox ul li.on {
	background: #12a5f8;
	color: #fff;
	cursor: pointer
}

.datepicker-sh .dp_timebox ul li.normal {
	color: #12a5f8;
	cursor: pointer
}

.datepicker-sh .dp_timebox ul li.normal:hover {
	background: #12b5f8;
	color: #fff
}

效果图,可自己根据需求自定义样式功能等

image.png