模仿win10样式,基于jquery的时间控件

工作需要,写了一个基于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>
*/


posted on 2016-09-23 15:06  丰云  阅读(276)  评论(0编辑  收藏  举报

导航