工作需要,写了一个基于jquery的时间控件,仿win10系统时间控件格式。
目前基本功能都有了,但时间格式只实现少数,但由于结构设计已经充分优化,填充起来非常容易。
这个控件相对网上其他的时间控件,代码少,易阅读,修改拓展方便,也适合新手参考学习。
if (typeof jQuery === 'undefined') { throw 'no jquery'; }
(function () {
window.UE_CONTROL_IDX = 0;
$.fn.GetRect = function () {
var r = $(this).get(0).getBoundingClientRect(),
t = document.documentElement.clientTop,
l = document.documentElement.clientLeft;
return {
top: r.top - t,
bottom: r.bottom - t,
left: r.left - l,
right: r.right - l
}
}
'use strict';
window.UEDate || (window.UEDate = {
viewTypes: {
's': 'yyyy-MM-ddThh:mm:ss',
't': 'h:m',
'y': 'y年m月',
'd': 'y/M/d/',
'm': 'm月d日',
'f': 'y年m月d日 h:m',
'g': 'y/m/d h:m',
'r': 'Sat, 05 Nov 2005 14:06:25 GMT',
'u': 'yyyy-MM-dd hh:mm:ssZ',
'T': 'h:m:s',
'Y': 'y年m月',
'D': 'y年m月d日',
'M': 'm月d日',
'F': 'y年m月d日 h:m:s',
'G': 'y/m/d h:m:s',
'R': 'Sat, 05 Nov 2005 14:06:25 GMT',
'U': 'y年m月d日 h:m:s',
'v': 'dd/MM/yyyy hh:mm:ss',
},
config: {
viewType: 'v',
width: 80,
height:30,
maxWidth: 360,
maxHeight: 200,
showBorder: true,
BorderColor: "#666",
BackColor: '#fff',
value: null,
fullMonth: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
simpleMonth: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'],
fullWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thurday', 'Friday', 'Saturday', 'Sunday'],
simpleWeek: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
style: ''
+ '<style id="ue_date_Style">'
+ ' .ue_date_frame {border:none;overflow:hidden;position:absolute;left:0;top:0;font-size:12px;user-select:none;margin: 0;padding: 1px;background-color:#fff;z-index:1;}'
+ ' .ue_date_content {border: 1px solid #fff;border-radius:2px;outline:none;position: relative;overflow:hidden;background-color:user-select:none; transparent;display: inline-block;float:left;padding:0 1px;height:18px;line-height:16px;}'
+ ' .ue_date_content:hover {border 1px solid #69c;}'
+ ' .ue_date_split {border: none;position: relative; overflow:hidden;width:6px;background-color: transparent;display: inline-block;float:left;padding:0;height:18px;line-height:20px;}'
+ ' .ue_date_over {border:none;width:210px; height:18px;overflow:hidden;text-align:center;position:relative;margin:5px 0;}'
+ ' .ue_date_over div {border:none;height:18px;line-height:18px;width:20px;text-align:center;border-radius:2px;cursor:pointer;}'
+ ' .ue_date_left {float:left;}.ue_date_left:hover{border:1px solid #69c;height:16px;line-height:16px;width:18px;}.ue_date_select {width:100px !important;display:inline-block;}.ue_date_right {float:right;}.ue_date_right:hover{border:1px solid #9cf;height:16px;line-height:16px;width:18px;}'
+ ' .ue_date_year {width:28px;}.ue_date_month {width:15px;} .ue_date_day {width:15px;}.ue_date_hour {width:15px;} .ue_date_minute {width:15px;} .ue_date_second {width:15px;}.ue_date_msec {width:28px;}'
+ ' .ue_date_pop {border:1px solid #999;border-radius:3px;width:210px;height:auto;overflow:hidden;position:absolute;font-size:12px;user-select:none;margin: 0;padding: 3px;background-color:#fff;display:none;z-index:2;}'
+ ' .ue_date_week {border:none;width:210px; height:18px;overflow:hidden;}'
+ ' .ue_date_week div {border:none;height:18px;line-height:18px;width:30px;text-align:center;border-radius:2px;display:inline-block;}'
+ ' .ue_date_dates {border:none;width:210px; height:auto;overflow:hidden;}.ue_date_selected {background:#9cf;}'
+ ' .ue_date_dates div {border:none;height:18px;line-height:18px;width:30px;text-align:center;border-radius:2px;display:inline-block;cursor:pointer;}'
+ ' .ue_date_months{border:none;width:210px; height:auto;overflow:hidden;display:none;}'
+ ' .ue_date_months div {border:none;height:18px;line-height:18px;width:42px;margin:5px;text-align:center;border-radius:2px;display:inline-block;cursor:pointer;}'
+ ' .ue_date_months div:hover {border:1px solid #69c;height:16px;line-height:16px;width:40px;}'
+ ' .ue_date_canhover{} .ue_date_canhover:hover {border:1px solid #69c;height:16px;line-height:16px;width:28px;}'
+ ' .ue_date_target {user-select:true;}'
+ '</style>',
},
toFixStr: function (value) {
return (value < 10 ? '0' : '') + value;
},
getDateFromText: function (t, f) {
if (t) {
f = f || this.config.viewType;
if (f == 'v') {
var s = t.split(' ');
var l = s[0].split('/');
t = l[2] + '-' + l[1] + '-' + l[0] + ' ' + (s.length > 1 ? s[1] : '');
} else {
t = t.replace('T', ' ');
}
try{
return new Date(t);
}catch(e){
return null;
}
} else {
return null;
}
},
getFmtDate: function (v, f) {
f = f || this.viewType;
switch (f) {
case 's': {
} break;
case 't': {
} break;
case 'y': {
} break;
case 'd': {
} break;
case 'm': {
} break;
case 'f': {
} break;
case 'g': {
} break;
case 'r': {
} break;
case 'u': {
return v.getFullYear() + '-' + (v.getMonth() + 1) + '-' + v.getDate() + ' ' + v.getHours() + ':' + v.getMinutes() + ':' + v.getSeconds();
} break;
case 'v': {
return v.getDate() + '/' + (v.getMonth() + 1) + '/' + v.getFullYear() + ' ' + v.getHours() + ':' + v.getMinutes() + ':' + v.getSeconds();
} break;
default: {
return v.getFullYear() + '-' + (v.getMonth() + 1) + '-' + v.getDate() + ' ' + v.getHours() + ':' + v.getMinutes() + ':' + v.getSeconds();
} break;
}
},
showCalendar: function () {
this.calendarDom = this.calendarDom || $(''
+ '<div class="ue_date_pop">'
+ ' <div class="ue_date_over">'
+ ' <div class="ue_date_left">◂</div>'
+ ' <div class="ue_date_select">2016年8月</div>'
+ ' <div class="ue_date_right">▸</div>'
+ ' </div>'
+ ' <div class="ue_date_week">'
+ ' <div>Mon</div><div>Tue</div><div>Wed</div><div>Thu</div><div>Fri</div><div>Sat</div><div>Sun</div>'
+ ' </div>'
+ ' <div class="ue_date_dates"></div>'
+ ' <div class="ue_date_months"></div>'
+ '</div>').appendTo($('body'));
this.calendarDom.show();
this.setCalendarDate(new Date(this.calendarYear, this.calendarMonth, 1, 0, 0, 0, 0));
this.setCalendarPosition();
},
setCalendarPosition: function () {
var ww = $(window).width(),
wh = $(window).height(),
bt = $('body').scrollTop(),
bl = $('body').scrollLeft(),
cw = this.calendarDom.outerWidth(),
ch = this.calendarDom.outerHeight(),
tw = this.target.outerWidth(),
th = this.target.outerHeight(),
rc = this.target.GetRect();
if ((rc.top + th + ch + 5) < wh) {
this.calendarDom.css({ top: rc.top + th });
} else {
this.calendarDom.css({ top: rc.top - ch });
}
if ((rc.left + cw) > ww) {
this.calendarDom.css({ left: (ww - cw) });
} else {
this.calendarDom.css({ left: rc.left });
}
},
setCalendarDate: function (dt) {
$(".ue_date_week").show();
$(".ue_date_months").hide();
var y = dt.getFullYear(), m = dt.getMonth(), day = dt.getDay(),
maxDay = (m == 1 ? (((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 28 : 29) : (m == 3 || m == 5 || m == 8 || m == 10) ? 30 : 31),
cnt = day + maxDay, p = $('.ue_date_dates').html('').show();
for (var i = j = 1; i < cnt; i++) {
if (i >= day && j <= maxDay) {
var o = $('<div class="ue_date_canhover">' + j + '</div>').appendTo(p);
if (j == this.date) {
o.addClass('ue_date_selected');
}
j++;
} else {
p.append('<div></div>');
}
}
$('.ue_date_select').html(this.config.fullMonth[m] + ',' + y);
this.calendarYear = dt.getFullYear();
this.calendarMonth = dt.getMonth();
this.bindCalendarEvent('d');
},
setCalendarMonth: function (m) {
$(".ue_date_week").hide();
$(".ue_date_dates").hide();
var d = $('.ue_date_months').html('').show();
for (var i = 0; i < 12; i++) {
var o = $('<div class="ue_date_canhover">' + this.config.simpleMonth[i] + '</div>').appendTo(d);
if (i == this.month) {
o.addClass('ue_date_selected');
}
}
$(".ue_date_select").html(this.calendarYear);
this.bindCalendarEvent('m');
},
setCalendarYear: function (y) {
var d = $('.ue_date_months').html('');
for (var i = 0; i < 12; i++) {
var o = $('<div class="ue_date_canhover">' + (y + i) + '</div>').appendTo(d);
if ((y + i) == this.year) {
o.addClass('ue_date_selected')
}
}
$(".ue_date_select").html(y + ' - ' + (y + 11));
this.bindCalendarEvent('y');
},
bindCalendarEvent: function (type) {
var dt = this;
$('.ue_date_left').off('click').on('click', function () {
if (type == 'd') {
var t = new Date(dt.calendarYear, dt.calendarMonth, 1, 0, 0, 0, 0);
t.setMonth(t.getMonth() - 1);
dt.setCalendarDate(t);
}
if (type == 'm') {
dt.calendarYear -= 1
$(".ue_date_select").html(dt.calendarYear);
}
if (type == 'y') {
var years = $(".ue_date_select").html().split('-');
var year = parseInt(years[0], 10);
dt.setCalendarYear(year - 12);
}
});
$('.ue_date_right').off('click').on('click', function () {
if (type == 'd') {
var t = new Date(dt.calendarYear, dt.calendarMonth, 1, 0, 0, 0, 0);
t.setMonth(t.getMonth() + 1);
dt.setCalendarDate(t);
}
if (type == 'm') {
dt.calendarYear += 1
$(".ue_date_select").html(dt.calendarYear);
}
if (type == 'y') {
var years = $(".ue_date_select").html().split('-');
var year = parseInt(years[0], 10);
dt.setCalendarYear(year + 12);
}
});
$('.ue_date_select').off('click').on('click', function () {
if (type == 'd') {
dt.setCalendarMonth();
}
if (type == 'm') {
dt.setCalendarYear(dt.calendarYear - 6);
}
});
$('.ue_date_canhover').off('click').on('click', function () {
if (type == 'd') {
var date = parseInt(this.innerHTML, 10);
dt.value = new Date(dt.calendarYear, dt.calendarMonth, date, dt.hour, dt.minute, dt.second, 0);
dt.setTargetValue();
$('.ue_date_frame').remove();
$('.ue_date_pop').hide();
}
if (type == 'm') {
arr = dt.config.simpleMonth;
for(var i in arr){
if (arr[i] == this.innerHTML) {
dt.calendarMonth = i;
var t = new Date(dt.calendarYear, i, 1, 0, 0, 0, 0);
dt.setCalendarDate(t);
}
}
}
if (type == 'y') {
dt.calendarYear = parseInt(this.innerHTML, 10);
dt.setCalendarMonth();
}
});
},
getMaxDate: function () {
var y = parseInt(this.frameDom.find('.ue_date_year').val(), 10);
var m = parseInt(this.frameDom.find('.ue_date_month').val(), 10);
return (m == 2 ? (((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 28 : 29) : (m == 4 || m == 6 || m == 9 || m == 11) ? 30 : 31);
},
changeValue: function (part, v) {
var t = parseInt(v, 10);
this[part] = part == 'month' ? t - 1 : t;
this.value = new Date(this.year, this.month, this.date, this.hour, this.minute, this.second, 0);
},
bindEvent: function () {
var dt = this;
this.frameDom.find('input').off('blur').on('blur', function () {
var v = this.value, o = $(this), part = o.attr('date_part'),
y = dt.value.getFullYear(),
m = dt.value.getMonth() + 1;
if (isNaN(v) || v < 0
|| (part == 'year' && (v < 1900 || v > 2100))
|| (part == 'month' && (v < 1 || v > 12))
|| (part == 'date' && (v < 1 || v > 31 || (m == 2 ? (((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? v > 28 : v > 29) : (m == 4 || m == 6 || m == 9 || m == 11) ? v > 30 : v > 31)))
|| (part == 'hour' && v > 23)
|| (part == 'minute' && v > 59)
|| (part == 'second' && v > 59)) {
o.css({ borderColor: '#f00' }).focus();
} else {
o.css({ borderColor: '#fff' });
dt.changeValue(part, v);
}
}).off('focus').on('focus',function () {
var o = $(this), part = o.attr('date_part');
if (o.css('borderColor') == 'rgb(255, 255, 255)') {
o.css({ borderColor: '#69c' });
}
});
$(document).off('keyup').on('keyup', function (e) {
e = e || window.event;
var t = e.srcElement || e.target;
if ($(t).hasClass('ue_date_content')) {
e.which = e.which == 13 ? 9 : e.which;
dt.keyStatus = 'keyup';
}
}).off('keydown').on('keydown', function (e) {
e = e || window.event;
var obj = document.activeElement;
if ($(obj).hasClass('ue_date_content')) {
var v = parseInt(obj.value, 10);
switch (e.which) {
case 38: {//上向键
dt.keyStatus = 'key38down';
var min = $(obj).hasClass('ue_date_year') ? 1900 :
$(obj).hasClass('ue_date_month') ? 1 :
$(obj).hasClass('ue_date_day') ? 1 : 0;
var up = setInterval(function () {
if (dt.keyStatus == 'key38down') {
if (v > min) {
obj.value = dt.toFixStr(v--);
} else {
clearInterval(up);
}
} else {
clearInterval(up);
}
}, 100);
if (v > min) {
obj.value = dt.toFixStr(v -= 1);
}
} break;
case 40: {//下向键
dt.keyStatus = 'key40down';
var max = $(obj).hasClass('ue_date_year') ? 2100 :
$(obj).hasClass('ue_date_month') ? 12 :
$(obj).hasClass('ue_date_day') ? dt.getMaxDate() :
$(obj).hasClass('ue_date_hour') ? 23 : 59;
var down = setInterval(function () {
if (dt.keyStatus == 'key40down') {
if (v < max) {
obj.value = dt.toFixStr(v++);
} else {
clearInterval(down);
}
} else {
clearInterval(down);
}
}, 100);
if (v < max) {
obj.value = dt.toFixStr(v += 1);
}
} break;
default: break;
}
}
}).off('click').on('click', function (e) {
e = e || window.event;
var t = e.srcElement || e.target;
var c = $(t).attr('class');
if (!c || c.indexOf('ue_date_') == -1) {
dt.setTargetValue();
$('.ue_date_frame').remove();
$('.ue_date_pop').hide();
}
});
},
setTargetValue: function () {
var v = this.getFmtDate(this.value);
this.target.html(v).text(v).val(v);
},
setValue: function (o,v) {
var v = this.getFmtDate(v, 'u');
tg.html(v).text(v).val(v);
},
setSeqByViewType: function () {
var idx = this.ue_control_idx;
switch (this.viewType) {
case 's': {
this.split3.html('T');
} break;
case 't': {
this.yearDom.hide();
this.split1.hide();
this.monthDom.hide();
this.split2.hide();
this.dateDom.hide();
this.split3.hide();
this.split5.hide();
this.secondDom.hide();
} break;
case 'y': {
this.split2.hide();
this.dateDom.hide();
this.split3.hide();
this.hourDom.hide();
this.split4.hide();
this.minuteDom.hide();
this.split5.hide();
this.secondDom.hide();
} break;
case 'd': {
this.split3.hide();
this.hourDom.hide();
this.split4.hide();
this.minuteDom.hide();
this.split5.hide();
this.secondDom.hide();
} break;
case 'm': {
this.yearDom.hide();
this.split1.hide();
this.split3.hide();
this.hourDom.hide();
this.split4.hide();
this.minuteDom.hide();
this.split5.hide();
this.secondDom.hide();
} break;
case 'f': {
} break;
case 'g': {
} break;
case 'r': {
} break;
case 'u': {
} break;
case 'v': {
this.dateDom.insertBefore(this.yearDom);
this.yearDom.insertBefore(this.split3);
this.split1.html('/');
this.split2.html('/');
} break;
default: {
} break;
}
},
initView: function () {
this.frameDom = $('<div class="ue_date_frame" idx="' + this.idx + '" ></div>').appendTo($('body'));
this.yearDom = $('<input class="ue_date_content ue_date_year" date_part="year" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.split1 = $('<div class="ue_date_split" idx="' + this.idx + '">-</div>').appendTo(this.frameDom);
this.monthDom = $('<input class="ue_date_content ue_date_month" date_part="month" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.split2 = $('<div class="ue_date_split" idx="' + this.idx + '">-</div>').appendTo(this.frameDom);
this.dateDom = $('<input class="ue_date_content ue_date_day" date_part="date" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.split3 = $('<div class="ue_date_split" idx="' + this.idx + '"> </div>').appendTo(this.frameDom);
this.hourDom = $('<input class="ue_date_content ue_date_hour" date_part="hour" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.split4 = $('<div class="ue_date_split" idx="' + this.idx + '">:</div>').appendTo(this.frameDom);
this.minuteDom = $('<input class="ue_date_content ue_date_minute" date_part="minute" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.split5 = $('<div class="ue_date_split" idx="' + this.idx + '">:</div>').appendTo(this.frameDom);
this.secondDom = $('<input class="ue_date_content ue_date_second" date_part="second" idx="' + this.idx + '" />').appendTo(this.frameDom);
this.yearDom.val(this.year);
this.monthDom.val(this.toFixStr(this.month + 1));
this.dateDom.val(this.toFixStr(this.date));
this.hourDom.val(this.toFixStr(this.hour));
this.minuteDom.val(this.toFixStr(this.minute));
this.secondDom.val(this.toFixStr(this.second));
this.setSeqByViewType();
var p = this.target.GetRect();
this.frameDom.css({ top: p.top + (this.config.height - 20) / 2, left: p.left }).show();
this.frameDom.children().first().focus().css({ borderColor: '#69c' });
},
initValue: function (s, f) {
var v = this.getDateFromText(s, f);
this.value = v;
this.year = this.calendarYear = v.getFullYear();
this.month = this.calendarMonth = v.getMonth();
this.date = v.getDate();
this.hour = v.getHours();
this.minute = v.getMinutes();
this.second = v.getSeconds();
},
bind: function (tg, f) {
if ($('#ue_date_Style').length < 1) {
$(this.config.style).appendTo('head');
}
var id = UE_CONTROL_IDX++;
tg.attr('idx', id).attr('tabindex', id).addClass('ue_date_target').attr('dateFormat', f || this.config.viewType)
.off('focus').on('focus', function () {
var idx = $(this).attr('idx');
if (idx * 1 != UEDate.idx) {
var frm = $('.ue_date_frame[idx=' + UEDate.idx + ']');
if (frm.length > 0) {
UEDate.setTargetValue();
frm.remove();
}
}
UEDate.show(this);
});
},
show: function (tg) {
var c = this.config;
this.target = t = $(tg);
this.idx = t.attr('tabindex') * 1;
this.viewType = t.attr('dateFormat') || this.config.viewType;
c.width = c.width || tg.width();
c.height = c.height || tg.height();
this.initValue(t.val() || t.html(), this.viewType);
this.initView();
this.bindEvent();
this.showCalendar();
},
});
$.fn.bindUEDate = function (f) {
UEDate.bind($(this), f);
};
}());
/* 调用示例
<div id="testDate1" style="width:160px; height:30px; border:1px solid #ddd; ">25/10/2016 15:24:36</div><br />
<input id="testDate2" style="width:160px; height:30px; border:1px solid #ddd;" value="18/9/2016 15:24:36" />
<script type="text/javascript">
var dt1 = $('#testDate1').bindUEDate();
var dt2 = $('#testDate2').bindUEDate();
</script>
*/