zoukankan      html  css  js  c++  java
  • 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 onclick="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- 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

  • 相关阅读:
    JS原生隐士标签扩展
    Asp.Net MVC强类型页面获取值几种方式
    Asp.Net MVC控制器获取视图传值几种方式
    vs2015 创建MVC项目
    C#后台HttpWebRequest模拟跨域Ajax请求,注册Windows服务到服务器上
    EF简介及CRUD简单DEMO
    Impala学习--代码生成(Code Generation)
    Impala源代码分析(2)-SQL解析与执行计划生成
    Impala源代码分析(3)-backend查询执行过程
    Impala源代码分析(1)-Impala架构和RPC
  • 原文地址:https://www.cnblogs.com/mirrortom/p/8093983.html
Copyright © 2011-2022 走看看