JS日期选择器

浏览器自带

浏览器自带日期控件,使用<input type="date">时,点击后会弹出.

1:EDGE 2:火狐 3:谷歌  三种都不一样.略胜于无

练习

模仿火狐日期控件的外观实现一个日期插件.效果

 PC

 

手机

使用控件

// 日期
<input onclick="MyDatePick()" />
// 日期加时间
<input onclick="MyDatePick({fmt:'datetime'})" />

 解决问题

  1.将日期框分四行区域,第一行是年,月,今天. 第二行是周,像是一个表格标题头.第三行是六行七列的日(天),第四行是时间.

  2.日期插件类生成整个DOM,绑定事件.css兼容手机和PC.

  3.六行七列的天,起点是选定月份的1号,再往前推到最近的周日.终点是选定月份的最后一天,再往后推到最近的周六.

  4.pc端可以手动输入input,手机端只点选,不能弹出键盘.

风格

  样式模仿火狐版本的日期框.实现最基本的选择日期到输入框功能.

  手机端固定显示在手机中间,占满宽度,按钮尺寸调大了些,便于手指点击.pc端显示在input框下方,对齐input左边.

  天排列由周日到周六,共42天.年份,月份,时分秒按钮弹出的选项面板同时只能显示一个.点击控件空白处可关闭.

  手机端控件得到焦点,input框点击后,不弹出键盘.pc端控件无焦点,点击控件外区域时关闭控件.

  年份选项区范围1900-2100  手工输入(INPUT框)年份0-9999可识别.时分秒范围0-23 0-59.

  不属于选定年月份中的天,选中的天,今天.在颜色上有区分

js

  1 ; (function ()
  2 {
  3     // window对象上使用的名字
  4     let exportName = 'MyDatePick';
  5     // datebox类名
  6     let dateboxCls = 'date-box';
  7     // 触发日期框的INPUT的JQ对象引用
  8     let inputJQ = null;
  9     // 日期框JQ对象
 10     let dateboxJQ = null;
 11     // 日期框运行时数据
 12     let cfg = null;
 13 
 14     // 在input上使用此方法. <input οnclick="MyDatePick()" />,需要时间部分: MyDatePick({fmt:datetime})
 15     let mydate = function (config)
 16     {
 17         let event = window.event || arguments.callee.caller.arguments[0]; // 获取event对象
 18         event.stopPropagation();
 19         let input = event.currentTarget;
 20         // 初始化已选年月日
 21         initDate(input, config);
 22         // 生成DOM
 23         let datedom = createDom();
 24         // 显示
 25         showDateBox(datedom);
 26         // 绑定事件
 27         dateboxJQ = $('.' + dateboxCls).eq(0);
 28         bindEventForShow();
 29     }
 30 
 31     // 初始化:已选年月,保存日期框的INPUT的JQ对象引用
 32     let initDate = function (input, config)
 33     {
 34         // input的JQ对象
 35         inputJQ = $(input);
 36 
 37         // 用inpupt的值初始化时间,为空则默认今天时间.input时间格式只支持 yyyy-MM-dd HH:mm:ss(时间,秒部分可省略)
 38         let inputval = $.trim(input.value);
 39         if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(inputval))
 40         {
 41             inputval = inputval + ' 00:00:00';
 42         } else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$/.test(inputval))
 43         {
 44             inputval = inputval + ':00';
 45         }
 46         else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/.test(inputval))
 47         { }
 48         else
 49         {
 50             inputval = null;
 51         }
 52         // console.log(inputval);
 53         // 不带时间部分的日期串,用parse解后,会有时差.
 54         let inputDate = Date.parse(inputval);
 55         let date = isNaN(inputDate) ? new Date((new Date()).setHours(0, 0, 0)) : new Date(inputDate);
 56         //
 57         //console.log(date);
 58         cfg = {};
 59         cfg.year = date.getFullYear();
 60         cfg.month = date.getMonth();
 61         cfg.day = date.getDate();
 62         cfg.hour = date.getHours();
 63         cfg.minute = date.getMinutes();
 64         cfg.second = date.getSeconds();
 65         // 显示格式为日期('yyyy-MM-dd'),或者日期和时间('yyyy-MM-dd HH:mm:ss')
 66         cfg.dateFmt = 'yyyy-MM-dd';
 67         cfg.fmtType = 1;
 68         if (config && config.fmt == 'datetime')
 69         {
 70             cfg.dateFmt = 'yyyy-MM-dd HH:mm:ss';
 71             cfg.fmtType = 2;
 72         }
 73     }
 74     // 显示日期框
 75     let showDateBox = function (datedom)
 76     {
 77         //console.log(datedom);
 78         // 根据日期框的位置显示日期DOM框
 79         let thisleft = inputJQ.offset().left + 'px';
 80         let thistop = inputJQ.offset().top + inputJQ.outerHeight() + 'px';
 81         // 576px以下屏(手机屏) 显示在屏幕中央(css媒体查询设为固定定位了)
 82         let ww = $(window).width();
 83         if (ww < 576)
 84         {
 85             thisleft = 0;
 86             thistop = '25vh';
 87         }
 88         $('.' + dateboxCls).remove();
 89         // 显示新的日期框
 90         $('body').append(String.DataBind(datedom, { left: thisleft, top: thistop, exportName: exportName }));
 91 
 92         // 576以上屏,input框要能手动输入,焦点在input框.在手机上使用选择,不使用手输,焦点在日期控件上.
 93         if (ww < 576)
 94         {
 95             $('.' + dateboxCls).eq(0).focus();
 96         } else
 97         {
 98 
 99         }
100     }
101     //========================================================//
102     // DOM生成
103     //========================================================//
104     // 生成整个日期框的DOM.并返回
105     let createDom = function ()
106     {
107         let datebox = '<div class="date-box" style="left:${left};top:${top}" tabindex="-1">{0}{1}{2}{3}</div>';
108         let ymtarea = String.Format('<div class="date-area-ymt">{0}{1}{2}</div>'
109             , createDom_Year()
110             , createDom_Month()
111             , createDom_Today());
112 
113         let weekarea = String.Format('<div class="date-area-week">{0}</div>'
114             , createDom_Week());
115 
116         let dayarea = String.Format('<div class="date-area-day">{0}</div>'
117             , createDom_Day());
118         // 时间区域
119         let tcarea = '';
120         if (cfg.fmtType == 2)
121         {
122             tcarea = String.Format('<div class="date-area-tc">{0}{1}{2}</div>'
123                 , createDom_Time()
124                 , createDom_Clear()
125                 , createDom_Ok());
126         }
127         return String.Format(datebox, ymtarea, weekarea, dayarea, tcarea);
128     }
129 
130     // 1.生成年份区内容 前进,后退,年份 按钮
131     let createDom_Year = function ()
132     {
133         let box = '<div class="date-area-year">{0}{1}{2}</div>';
134         let prevbtn = '<a class="date-btn-prev">&lt;</a>';
135         let yearbtn = String.Format(
136             '<b class="date-btn-year" val="{0}">{0}年</b>'
137             , cfg.year);
138         let nextbtn = '<a class="date-btn-next">&gt;</a>';
139         return String.Format(box, prevbtn, yearbtn, nextbtn);
140     }
141 
142     // 1.1生成年份下拉选择框. selectedYear:可指定一个年份为已选定
143     let createDom_YearSelect = function (selectedYear)
144     {
145         let ydoms = '';
146         let ylist = domYear_Data();
147         for (let i = 0; i < ylist.length; i++)
148         {
149             ydoms += String.Format('<b class="date-option-year {0}" val="{1}">{1}</b>',
150                 ylist[i] == selectedYear ? "selected" : "", ylist[i]);
151         }
152         return String.Format('<div class="date-select-year">{0}</div>', ydoms);
153     }
154 
155     // 2.生成月份区 前进,后退,月份 按钮
156     let createDom_Month = function ()
157     {
158         let box = '<div class="date-area-month">{0}{1}{2}</div>';
159         let prevbtn = '<a class="date-btn-prev">&lt;</a>';
160         let monthbtn = String.Format('<b class="date-btn-month" val="{0}">{1}月</b>'
161             , cfg.month, cfg.month + 1);
162         let nextbtn = '<a class="date-btn-next">&gt;</a>';
163         return String.Format(box, prevbtn, monthbtn, nextbtn);
164     }
165 
166     // 2.1生成月份下拉选择框. selectedMonth:可指定一个月份为已选定
167     let createDom_MonthSelect = function (selectedMonth)
168     {
169         let mdoms = '';
170         for (let i = 0; i < 12; i++)
171         {
172             mdoms += String.Format(
173                 '<b class="date-option-month {0}" val="{1}">{2}</b>'
174                 , selectedMonth == i ? "selected" : '', i, i + 1);
175         }
176         return String.Format('<div class="date-select-month">{0}</div>', mdoms);
177     }
178 
179     // 3.生成星期标题头
180     let createDom_Week = function ()
181     {
182         let weeksdom = '';
183         let weeks = ['日', '一', '二', '三', '四', '五', '六'];
184         for (let i = 0; i < weeks.length; i++)
185         {
186             weeksdom += String.Format('<b class="date-item-week{0}">{1}</b>'
187                 , i == 0 || i == 6 ? ' date-item-weekend' : '', weeks[i]);
188         }
189         return weeksdom;
190     }
191 
192     // 4.生成天选项 daylist:日数据.不传则使用选定年月计算出日
193     let createDom_Day = function (daylist)
194     {
195         let data = daylist || domDay_Data();
196         let daydoms = '';
197         for (var i = 0; i < data.length; i++)
198         {
199             let json = data[i];
200             let daydom = '<b class="date-item-day${istoday}${isdayinmonth}${isselected}${isweekend}" year="${yyyy}" month="${MM}" day="${dd}">${dd}</b>';
201             json.istoday = json.Istoday ? ' date-item-today' : '';
202             json.isselected = json.Isselected ? ' selected' : '';
203             json.isdayinmonth = json.Isdayinmonth ? '' : ' date-item-dayoutmonth';
204             json.isweekend = json.Isweekend ? ' date-item-weekend' : '';
205             json.exportName = exportName;
206             daydoms += String.DataBind(daydom, json);
207         }
208         return daydoms;
209     }
210     // 5.生成时分秒区域
211     let createDom_Time = function ()
212     {
213         let box = '<div class="date-area-time">{0}{1}{2}</div>';
214         let hour = String.Format('<b class="date-btn-time date-btn-hour">{0}</b>:', cfg.hour);
215         let minute = String.Format('<b class="date-btn-time date-btn-minute">{0}</b>:',cfg.minute);
216         let second = String.Format('<b class="date-btn-time date-btn-second">{0}</b>', cfg.second);
217         return String.Format(box, hour, minute, second);
218     }
219     // 5.1生成小时选择框
220     let createDom_HourSelect = function ()
221     {
222         let doms = '';
223         for (let i = 0; i < 24; i++)
224         {
225             doms += String.Format(
226                 '<b class="date-option-hour" val="{0}">{0}</b>', i);
227         }
228         return String.Format('<div class="date-select-hour">{0}</div>', doms);
229     }
230     // 5.2生成分钟,秒钟选择框
231     let createDom_MinuteSelect = function ()
232     {
233         let doms = '';
234         for (let i = 0; i < 60; i++)
235         {
236             doms += String.Format(
237                 '<b class="date-option-minute" val="{0}">{0}</b>', i);
238         }
239         return String.Format('<div class="date-select-minute">{0}</div>', doms);
240     }
241     // 5.3生成秒钟选择框
242     let createDom_SecondSelect = function ()
243     {
244         let doms = '';
245         for (let i = 0; i < 60; i++)
246         {
247             doms += String.Format('<b class="date-option-second" val="{0}">{0}</b>', i);
248         }
249         return String.Format('<div class="date-select-second">{0}</div>', doms);
250     }
251     // 6.生成今天按钮区域
252     let createDom_Today = function ()
253     {
254         return '<div class="date-area-today"><a class="date-btn-today">今天</a></div>';
255     }
256     // 7.生成清除按钮区域
257     let createDom_Clear = function ()
258     {
259         let box = '<div class="date-area-clear">{0}</div>';
260         return String.Format(box, '<a class="date-btn-clear">清空</a>');
261     }
262     // 8.生成确定按钮区域 
263     let createDom_Ok = function ()
264     {
265         let box = '<div class="date-area-ok">{0}</div>';
266         return String.Format(box, '<a class="date-btn-ok">确定</a>');
267     }
268 
269     // 根据选定的年,月刷新日(用于当在日期框上操作年,月等会改变年月的动作时)
270     // yyyy:指定年,mm:指定月 daysdom:日的父级DOM的JQ对象(.daysrows)
271     let resetDaysDom = function (yyyy, mm)
272     {
273         // 计算出指定年月的日数据
274         let dayslist = domDay_Data(yyyy, mm);
275         // 生成天DOM
276         let daysdom = createDom_Day(dayslist);
277         // 更新天DOM
278         dateboxJQ.find('.date-area-day').html(daysdom);
279         // 事件绑定
280         bindEventForDaySelected();
281     }
282 
283     //=================================================//
284     //    为DOM提供的数据,年份 日
285     //=================================================//
286     // 根据已选年计算年份选项
287     let domYear_Data = function ()
288     {
289         // 年份选择范围固定在[1900-2100]
290         let data = [];
291         for (let i = 1900; i < 2101; i++)
292         {
293             data.push(i);
294         }
295         return data;
296     }
297 
298     // 根据已选年月或者传入指定年月,计算日的起始和结束
299     // 日(天)总共六行七列42个,含已选年月所有日, 前推至最近的周日, 后推至最近或次近的周六
300     let domDay_Data = function (yyyy, mm)
301     {
302         // 指定年 超范围则设为当天年
303         let seledY = $.isNumeric(yyyy) ? parseInt(yyyy) : cfg.year;
304         // 指定月 超范围设为当天月
305         let seledM = $.isNumeric(mm) ? parseInt(mm) : cfg.month;
306 
307         // 指定年月的起止日(1~xx号)
308         let startDay = new Date(seledY, seledM, 1);
309         //let endDay = new Date(seledY, seledM + 1, 0);
310 
311         // 日期起点为指定年月的1号前推到最近的周日,终点为该月最后一天后推到最近的周六
312         startDay.setDate(1 - startDay.getDay());
313         //endDay.setDate(endDay.getDate() + (6 - endDay.getDay()));
314         // 当天日期
315         let todaystr = (new Date()).ToString('yyyyMMdd');
316         let daylist = [];
317         for (let i = 0; i < 42; i++)
318         {
319             let json = {};
320             json.yyyy = startDay.getFullYear();
321             json.MM = startDay.getMonth();
322             json.dd = startDay.getDate();
323             // 日是否属于指定年月中的日
324             json.Isdayinmonth = json.MM == seledM;
325             // 日是否为今天 
326             json.Istoday = startDay.ToString('yyyyMMdd') == todaystr;
327             // 日是否选定(等于文本框中已选日)
328             json.Isselected =
329                 (json.yyyy == cfg.year && json.MM == cfg.month
330                     && json.dd == cfg.day);
331             // 这天是否为周六日(这里未真正判断,而是根据位置判断,每七天为一行,行首周日行尾周六)
332             json.Isweekend = (i % 7 == 0 || (i + 1) % 7 == 0);
333             //
334             startDay.setDate(json.dd + 1);
335             daylist.push(json);
336         }
337         //console.log(daylist);
338         return daylist;
339     }
340 
341     //===============================================================//
342     //    事件方法:年,月的前进后退按钮,年月选择按钮,今天按钮
343     //===============================================================//
344     // 控件显示后,要绑定控件的基础事件.
345     let bindEventForShow = function ()
346     {
347         bindEventForDateBox();
348         bindEventForYearBtn();
349         bindEventForMonthBtn();
350         bindEventForYearMonthPrevNext();
351         bindEventForTodayBtn();
352         bindEventForHourBtn();
353         bindEventForMinBtn();
354         bindEventForSecBtn();
355         bindEventForDaySelected();
356         bindEventForClearBtn();
357         bindEventForOkBtn();
358     }
359 
360     let bindEventForDateBox = function ()
361     {
362         // 点击日期控件以内区域,阻止冒泡到根
363         dateboxJQ.on('click', function (event)
364         {
365             event.stopPropagation();
366             // 点击空白位置时,关闭已经打开的年,月,日,时,分,秒的选择框.需要在子元素上取消冒泡
367             $(this).find('[class^=date-select]').remove();
368         })
369     }
370     let bindEventForYearBtn = function ()
371     {
372         // 点击年按钮 显示年选择框
373         dateboxJQ.find('.date-btn-year').on('click', function (event)
374         {
375             event.stopPropagation();
376             let thisobj = event.currentTarget;
377             //
378             let seledY = $(thisobj).attr('val');
379             // 年份选择框 .date-select-year
380             let yearopsbox = $(thisobj).parent().find('.date-select-year');
381             // 如果已经显示则关闭
382             if (yearopsbox.length == 1)
383             {
384                 yearopsbox.remove(); return;
385             }
386             // 先关闭其它弹出窗
387             dateboxJQ.find('[class^=date-select]').remove();
388             // 生成年份选择框,填充到年份选择框中
389             $(thisobj).parent().append(createDom_YearSelect(seledY));
390             // 定位已选年份到滚动框的中间(视口可见范围内)
391             let yopsbox = $(thisobj).parent().find('.date-select-year');
392             let yseled = yopsbox.find('.selected');
393             if (yseled.length == 0)
394                 yseled = yopsbox.find('[val=' + (new Date()).getFullYear() + ']');
395             // 计算这个年份选项离父框的TOP值,然后滚动条滚动这个值-父框高/2
396             let scrollval = yseled.position().top - yopsbox.height() / 2;
397             yopsbox.scrollTop(scrollval);
398             // 绑定年份选择点击事件
399             bindEventForYearSelected();
400         })
401     }
402     let bindEventForMonthBtn = function ()
403     {
404         // 点击月按钮 显示月选择框
405         dateboxJQ.find('.date-btn-month').on('click', function (event)
406         {
407             event.stopPropagation();
408             let thisobj = event.currentTarget;
409             //
410             let seledM = $(thisobj).attr('val');
411             let monthsops = $(thisobj).parent().find('.date-select-month');
412             // 如果已经显示则关闭
413             if (monthsops.length == 1)
414             {
415                 monthsops.remove(); return;
416             }
417             // 先关闭其它弹出窗
418             dateboxJQ.find('[class^=date-select]').remove();
419             $(thisobj).parent().append(createDom_MonthSelect(seledM));
420             // 绑定月分选项点击事件
421             bindEventForMonthSelected();
422         })
423     }
424     let bindEventForYearSelected = function ()
425     {
426         // 点击年份选项 选定一个年份 
427         dateboxJQ.find('.date-option-year').on('click', function (event)
428         {
429             event.stopPropagation();
430             let thisobj = event.currentTarget;
431             // 
432             // 所选年份值
433             let y = $(thisobj).attr('val');
434             // 更新年份按钮显示值
435             dateboxJQ.find('.date-btn-year').attr('val', y).html(y + '年');
436             // 关闭年份选择框
437             $(thisobj).parent().remove();
438             // 刷新 日
439             let m = dateboxJQ.find('.date-btn-month').attr('val');
440             resetDaysDom(y, m);
441         })
442     }
443     let bindEventForMonthSelected = function ()
444     {
445         // 点击月份选项 选定一个月份
446         dateboxJQ.find('.date-option-month').on('click', function (event)
447         {
448             event.stopPropagation();
449             let thisobj = event.currentTarget;
450             // 
451             // 所选月份值
452             let m = parseInt($(thisobj).attr('val'));
453             dateboxJQ.find('.date-btn-month').attr('val', m).html((m + 1) + '月');
454             // 关闭月份选择框
455             $(thisobj).parent().remove();
456             // 刷新 日
457             let y = dateboxJQ.find('.date-btn-year').attr('val');
458             resetDaysDom(y, m);
459         })
460     }
461     let bindEventForYearMonthPrevNext = function ()
462     {
463         // 点击年份,月份的前进和后退按钮 btntype:1=年按钮,2=月按钮. dir:1=前进,2=后退
464         dateboxJQ.find('.date-btn-prev,.date-btn-next').on('click', function (event)
465         {
466             event.stopPropagation();
467             let thisobj = event.currentTarget;
468             //
469             let btntype = $(thisobj).parent().hasClass('date-area-year') ? 1 : 2;
470             let dir = $(thisobj).hasClass('date-btn-next') ? 1 : 2;
471             //
472             let ybtn = dateboxJQ.find('.date-btn-year');
473             let mbtn = dateboxJQ.find('.date-btn-month');
474             let y = parseInt(ybtn.attr('val'));
475             let m = parseInt(mbtn.attr('val'));
476             // 计算并刷新年或月按钮值 年份前进后退值[1-9999]
477             if (btntype == 1)
478             {
479                 y = dir == 1 ? y + 1 : y - 1;
480                 if (y < 1) y = 9999;
481                 else if (y > 9999) y = 1;
482             }
483             else if (btntype == 2)
484             {
485                 m = dir == 1 ? m + 1 : m - 1;
486                 if (m < 0)
487                 {
488                     m = 11;
489                     // 年往后退一年,如果为1年,则不变
490                     if (y > 1)
491                         y = y - 1;
492                 }
493                 else if (m > 11)
494                 {
495                     m = 0;
496                     // 年往前进一年,如果为9999年,则不变
497                     if (y < 9999)
498                         y = y + 1;
499                 }
500             }
501             ybtn.attr('val', y).html(y + '年');
502             mbtn.attr('val', m).html((m + 1) + '月');
503             // 刷新日
504             //console.log(y+'----'+m);
505             resetDaysDom(y, m);
506         })
507     }
508     let bindEventForTodayBtn = function ()
509     {
510         // 点击今天按钮 设置今天日期到input框
511         dateboxJQ.find('.date-btn-today').on('click', function (event)
512         {
513             event.stopPropagation();
514             let thisobj = event.currentTarget;
515             //
516             let today = new Date(new Date().toLocaleDateString());
517             inputJQ.val(today.ToString(cfg.dateFmt));
518             //
519             mydate.close();
520         })
521     }
522     let bindEventForHourBtn = function ()
523     {
524         // 点击小时按钮 显示小时选择框
525         dateboxJQ.find('.date-btn-hour').on('click', function (event)
526         {
527             event.stopPropagation();
528             let thisobj = event.currentTarget;
529             //
530             let hourselecct = $(thisobj).parent().find('.date-select-hour');
531             // 点击时分秒下拉框按钮时,先取消其按钮的打开样式,打开后,再给自己加上打开样式
532             $(thisobj).parent().find('.date-btn-time').removeClass('open');
533             // 如果已经显示则关闭
534             if (hourselecct.length == 1)
535             {
536                 hourselecct.remove(); return;
537             }
538             // 先关闭其它弹出窗
539             dateboxJQ.find('[class^=date-select]').remove();
540             $(thisobj).parent().append(createDom_HourSelect());
541             $(thisobj).addClass('open');
542             // 绑定小时选项点击事件
543             bindEventForHourSelected();
544         })
545     }
546     let bindEventForMinBtn = function ()
547     {
548         // 点击分钟按钮 显示分钟选择框
549         dateboxJQ.find('.date-btn-minute').on('click', function (event)
550         {
551             event.stopPropagation();
552             let thisobj = event.currentTarget;
553             //
554             let minselecct = $(thisobj).parent().find('.date-select-minute');
555             // 点击时分秒下拉框按钮时,先取消其按钮的打开样式,打开后,再给自己加上打开样式
556             $(thisobj).parent().find('.date-btn-time').removeClass('open');
557             // 如果已经显示则关闭
558             if (minselecct.length == 1)
559             {
560                 minselecct.remove(); return;
561             }
562             // 先关闭其它弹出窗
563             dateboxJQ.find('[class^=date-select]').remove();
564             $(thisobj).parent().append(createDom_MinuteSelect());
565             $(thisobj).addClass('open');
566             // 绑定分钟选项点击事件
567             bindEventForMinSelected();
568         })
569     }
570     let bindEventForSecBtn = function ()
571     {
572         // 点击秒钟按钮 显示秒钟选择框
573         dateboxJQ.find('.date-btn-second').on('click', function (event)
574         {
575             event.stopPropagation();
576             let thisobj = event.currentTarget;
577             //
578             let secselecct = $(thisobj).parent().find('.date-select-second');
579             // 点击时分秒下拉框按钮时,先取消其按钮的打开样式,打开后,再给自己加上打开样式
580             $(thisobj).parent().find('.date-btn-time').removeClass('open');
581             // 如果已经显示则关闭
582             if (secselecct.length == 1)
583             {
584                 secselecct.remove(); return;
585             }
586             // 先关闭其它弹出窗
587             dateboxJQ.find('[class^=date-select]').remove();
588             $(thisobj).parent().append(createDom_SecondSelect());
589             $(thisobj).addClass('open');
590             // 绑定秒钟选项点击事件
591             bindEventForSecSelected();
592         })
593     }
594     let bindEventForHourSelected = function ()
595     {
596         // 选择小时 修改小时按钮显示值
597         dateboxJQ.find('.date-option-hour').on('click', function (event)
598         {
599             event.stopPropagation();
600             let thisobj = event.currentTarget;
601             //
602             let h = $(thisobj).attr('val');
603             dateboxJQ.find('.date-btn-hour').html(h);
604             cfg.hour = h;
605             //
606             $(thisobj).parent().remove();
607         })
608     }
609     let bindEventForMinSelected = function ()
610     {
611         // 选择分钟 修改按钮显示值
612         dateboxJQ.find('.date-option-minute').on('click', function (event)
613         {
614             event.stopPropagation();
615             let thisobj = event.currentTarget;
616             //
617             let m = $(thisobj).attr('val');
618             dateboxJQ.find('.date-btn-minute').html(m);
619             cfg.minute = m;
620             //
621             $(thisobj).parent().remove();
622         })
623     }
624     let bindEventForSecSelected = function ()
625     {
626         // 选择秒钟 修改按钮显示值
627         dateboxJQ.find('.date-option-second').on('click', function (event)
628         {
629             event.stopPropagation();
630             let thisobj = event.currentTarget;
631             //
632             let s = $(thisobj).attr('val');
633             dateboxJQ.find('.date-btn-second').html(s);
634             cfg.second = s;
635             //
636             $(thisobj).parent().remove();
637         })
638     }
639     let bindEventForDaySelected = function ()
640     {
641         // 选择天 设置这天日期到Input框
642         dateboxJQ.find('.date-item-day').on('click', function (event)
643         {
644             event.stopPropagation();
645             let thisobj = event.currentTarget;
646             //
647             let date = new Date($(thisobj).attr('year'), $(thisobj).attr('month')
648                 , $(thisobj).attr('day'),cfg.hour,cfg.minute,cfg.second);
649             inputJQ.val(date.ToString(cfg.dateFmt));
650             //
651             mydate.close();
652         })
653     }
654     let bindEventForClearBtn = function ()
655     {
656         // 点击清空
657         dateboxJQ.find('.date-btn-clear').on('click', function (event)
658         {
659             event.stopPropagation();
660             let thisobj = event.currentTarget;
661             //
662             inputJQ.val('');
663             mydate.close();
664         })
665     }
666     let bindEventForOkBtn = function ()
667     {
668         // 点击确定按钮
669         dateboxJQ.find('.date-btn-ok').on('click', function (event)
670         {
671             event.stopPropagation();
672             let thisobj = event.currentTarget;
673             //
674             // 找到选中的日 设置到Input框 如果没有选中的日,使用今天
675             let seledDay = dateboxJQ.find('.date-item-day.selected');
676             let inputVal = seledDay.length == 0
677                 ? new Date(new Date().toLocaleDateString(), cfg.hour, cfg.minute, cfg.second)
678                 : new Date(seledDay.attr('year'), seledDay.attr('month'), seledDay.attr('day')
679                     , cfg.hour, cfg.minute, cfg.second);
680             
681             inputJQ.val(inputVal.ToString(cfg.dateFmt));
682             //
683             mydate.close();
684         })
685     }
686 
687     // 关闭日期框
688     mydate.close = function ()
689     {
690         dateboxJQ = null;
691         inputJQ = null;
692         cfg = null;
693         $('.' + dateboxCls).remove();
694     }
695 
696     // 点击日期控件以外区域,关闭控件. 
697     $(document).click(function ()
698     {
699         mydate.close();
700     })
701     //
702     window[exportName] = mydate;
703 })();
mydatepick

css

  1 .date-box {
  2   position: absolute;
  3   width: 308px;
  4   cursor: default;
  5   border: 1px solid #e9ecef;
  6   padding: 10px 5px;
  7   text-align: center;
  8   box-shadow: 1px 1px 10px #dee2e6;
  9   background-color: #fff;
 10   outline: none;
 11   -webkit-user-select: none;
 12   -moz-user-select: none;
 13   -ms-user-select: none;
 14   user-select: none; }
 15 
 16 .date-area-ymt {
 17   display: flex; }
 18 
 19 .date-area-year, .date-area-month, .date-area-today {
 20   position: relative;
 21   padding: 0 4px; }
 22 
 23 .date-area-year {
 24   flex: 0 1 44%; }
 25 
 26 .date-area-month {
 27   flex: 0 1 38%; }
 28 
 29 .date-area-today {
 30   flex: 0 1 18%; }
 31 
 32 .date-area-week {
 33   display: flex;
 34   padding: 5px 0; }
 35 
 36 .date-area-day {
 37   display: flex;
 38   flex-wrap: wrap; }
 39 
 40 .date-area-tc {
 41   display: flex;
 42   position: relative; }
 43 
 44 .date-area-time, .date-area-clear, .date-area-ok {
 45   border-top: 1px solid #e9ecef;
 46   padding-top: 10px; }
 47 
 48 .date-area-time {
 49   flex: 0 1 64%; }
 50 
 51 .date-area-clear, .date-area-ok {
 52   flex: 0 1 18%;
 53   padding-left: 4px;
 54   padding-right: 4px; }
 55 
 56 .date-select-year, .date-select-month, .date-select-hour, .date-select-minute, .date-select-second {
 57   display: flex;
 58   flex-wrap: wrap;
 59   position: absolute;
 60   left: 0;
 61   border: 1px solid #dee2e6;
 62   border-radius: 4px;
 63   border-top: none;
 64   background-color: #f8f9fa;
 65   z-index: 9999; }
 66 
 67 .date-select-month {
 68   width: 100%; }
 69 
 70 .date-select-year {
 71   width: 200px;
 72   height: 180px;
 73   overflow-x: hidden;
 74   overflow-y: scroll;
 75   padding: 10px 0; }
 76 
 77 .date-select-hour, .date-select-minute, .date-select-second {
 78   width: 100%;
 79   bottom: 28px; }
 80 
 81 .date-option-year, .date-option-month, .date-option-hour, .date-option-minute, .date-option-second {
 82   border-bottom: 1px solid #dee2e6;
 83   height: 28px;
 84   line-height: 28px;
 85   font-weight: 500; }
 86 
 87 .date-option-year, .date-option-month {
 88   flex: 0 1 33.33333333%; }
 89 
 90 .date-option-year:hover, .date-option-month:hover, .date-option-hour:hover, .date-option-minute:hover {
 91   background-color: #dee2e6; }
 92 
 93 .date-option-year.selected, .date-option-month.selected {
 94   background-color: #007bff; }
 95 
 96 .date-option-hour {
 97   flex: 0 1 16.66666666%; }
 98 
 99 .date-option-minute, .date-option-second {
100   flex: 0 1 10%; }
101 
102 .date-btn-year, .date-btn-month, .date-btn-today, .date-btn-prev, .date-btn-next, .date-btn-time, .date-btn-clear, .date-btn-ok {
103   display: inline-block;
104   font-weight: 600;
105   border: 1px solid #e9ecef;
106   border-radius: 3px;
107   height: 26px;
108   line-height: 26px;
109   cursor: pointer; }
110 
111 .date-btn-year, .date-btn-month {
112   color: #6c757d;
113   width: calc(100% - 52px); }
114 
115 .date-btn-today, .date-btn-prev, .date-btn-next {
116   color: #007bff; }
117 
118 .date-btn-today, .date-btn-clear, .date-btn-ok {
119   width: 100%; }
120 
121 .date-btn-clear, .date-btn-ok {
122   font-weight: 500;
123   color: #6c757d; }
124 
125 .date-btn-prev, .date-btn-next {
126   width: 26px; }
127 
128 .date-btn-time {
129   font-weight: 500;
130   width: 32px;
131   margin: 0 5px; }
132 
133 .date-btn-time.open {
134   color: #fff;
135   background-color: #007bff; }
136 
137 .date-item-week, .date-item-day {
138   flex: 0 1 14.28571428%;
139   font-weight: 500;
140   height: 28px;
141   line-height: 28px;
142   border-radius: 3px; }
143 
144 .date-item-week {
145   font-weight: 600; }
146 
147 .date-item-weekend {
148   color: #dc3545; }
149 
150 .date-item-day:hover {
151   background-color: #e9ecef; }
152 
153 .date-item-dayoutmonth {
154   opacity: .3; }
155 
156 .date-item-day.selected:not(.date-item-today) {
157   background-color: #dee2e6; }
158 
159 .date-item-today {
160   color: #fff;
161   background-color: #007bff; }
162 
163 @media only screen and (max-width: 576px) {
164   .date-box {
165     position: fixed;
166     width: calc(100vw - 2px);
167     height: 312px;
168     border-color: #007bff;
169     right: 0;
170     margin: auto; }
171   .date-btn-year, .date-btn-month, .date-btn-today, .date-btn-prev, .date-btn-next, .date-btn-time, .date-btn-clear, .date-btn-ok {
172     height: 36px;
173     line-height: 36px; }
174   .date-btn-year, .date-btn-month {
175     width: calc(100% - 72px); }
176   .date-btn-prev, .date-btn-next {
177     width: 36px; }
178   .date-option-year, .date-option-month, .date-option-hour, .date-option-minute, .date-option-second {
179     height: 36px;
180     line-height: 36px; }
181   .date-select-hour, .date-select-minute, .date-select-second {
182     bottom: 38px; } }
css

 

 JS原生版本

https://github.com/mirrortom/webcoms/tree/master/mydatepick

转载于:https://www.cnblogs.com/mirrortom/p/8093983.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用第三方库或者自己编写代码实现JavaScript日期选择器。其中比较常用的第三方库有jQuery UI Datepicker、Bootstrap Datepicker等。 如果使用jQuery UI Datepicker,可以在HTML中引入jQuery和jQuery UI的库文件,然后在JavaScript中调用datepicker()方法即可。例如: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery UI Datepicker</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <script> $(function() { $("#datepicker").datepicker(); }); </script> </head> <body> <p>Date: <input type="text" id="datepicker"></p> </body> </html> ``` 如果使用Bootstrap Datepicker,可以在HTML中引入Bootstrap和Bootstrap Datepicker的库文件,然后在JavaScript中调用datepicker()方法即可。例如: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Bootstrap Datepicker</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css"> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script> <script> $(function() { $("#datepicker").datepicker(); }); </script> </head> <body> <p>Date: <input type="text" id="datepicker"></p> </body> </html> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值