移动端底部弹框选择日期

<input readonly class="form-control" type="text" id="date-group1-4" placeholder="请选择">
new Jdate({
                el: '#date-group1-4',
                format: 'YYYY-MM-DD hh:mm',
                // beginYear: 2000,
                // endYear: 2100
            })
<script src="./js/jdate.js"></script>

代码如下:

/**
 * Jdate 2.0.1
 * Copyright 2017-2019
 * weijhfly https://github.com/weijhfly/jqueryDatePlugin
 * Licensed under MIT
 * Released on: jan 24, 2017
 */

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.Jdate = factory());
}(this, function () { 'use strict';

  function styleInject(css, ref) {
    if ( ref === void 0 ) ref = {};
    var insertAt = ref.insertAt;

    if (!css || typeof document === 'undefined') { return; }

    var head = document.head || document.getElementsByTagName('head')[0];
    var style = document.createElement('style');
    style.type = 'text/css';

    if (insertAt === 'top') {
      if (head.firstChild) {
        head.insertBefore(style, head.firstChild);
      } else {
        head.appendChild(style);
      }
    } else {
      head.appendChild(style);
    }

    if (style.styleSheet) {
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }
  }

  var css = "ul{margin:0;padding:0}li{list-style-type:none}.jdate-container{font-size:20px;color:#333;text-align:center}.jdate-container header{position:relative;line-height:60px;font-size:18px;border-bottom:1px solid #e0e0e0}.jdate-container .jdate-mask{position:fixed;width:100%;height:100%;top:0;left:0;background:#000;opacity:.4;z-index:999}.jdate-container .jdate-panel{position:fixed;bottom:0;left:0;width:100%;height:273px;z-index:1000;background:#fff;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-delay:0s;animation-delay:0s;-webkit-animation-iteration-count:1;animation-iteration-count:1}.jdate-container .jdate-btn{position:absolute;left:0;top:0;height:100%;padding:0 15px;color:#666;font-size:16px;cursor:pointer;-webkit-tap-highlight-color:transparent}.jdate-container .jdate-confirm{left:auto;right:0;color:#007bff}.jdate-container .jdate-content{position:relative;top:20px}.jdate-container .jdate-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.jdate-container .jdate-wrapper>div{position:relative;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;height:173px;line-height:36px;overflow:hidden;-webkit-flex-basis:-8e;-ms-flex-preferred-size:-8e;flex-basis:-8e;width:1%}.jdate-container .jdate-wrapper ul{position:absolute;left:0;top:0;width:100%;margin-top:68px}.jdate-container .jdate-wrapper li{height:36px}.jdate-container .jdate-dim{position:absolute;left:0;top:0;width:100%;height:68px;background:-o-linear-gradient(bottom,hsla(0,0%,100%,.4),hsla(0,0%,100%,.8));background:-webkit-gradient(linear, left bottom, left top, from(hsla(0, 0%, 100%, 0.4)), to(hsla(0, 0%, 100%, 0.8)));background:-o-linear-gradient(bottom, hsla(0, 0%, 100%, 0.4), hsla(0, 0%, 100%, 0.8));background:linear-gradient(0deg,hsla(0,0%,100%,.4),hsla(0,0%,100%,.8));pointer-events:none;-webkit-transform:translateZ(0);transform:translateZ(0);z-index:10}.jdate-container .mask-top{border-bottom:1px solid #ebebeb}.jdate-container .mask-bottom{top:auto;bottom:1px;border-top:1px solid #ebebeb}.jdate-container .fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}.jdate-container .fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeIn{0%{bottom:-273px}to{bottom:0}}@keyframes fadeIn{0%{bottom:-273px}to{bottom:0}}@-webkit-keyframes fadeOut{0%{bottom:0}to{bottom:-273px;display:none}}@keyframes fadeOut{0%{bottom:0}to{bottom:-273px;display:none}}@media screen and (max-width:414px){.jdate-container{font-size:18px}}@media screen and (max-width:320px){.jdate-container{font-size:15px}}";
  styleInject(css);

  var version = "2.0.1";

  var $ = typeof $ != 'undefined' ? $ : typeof jQuery != 'undefined' ? jQuery : null,
      h = 36;

  Jdate.usejQuery = function (jQuery) {
      $ = jQuery;
  };
  function Jdate(config) {
      if (!$) {
          console.error('jQuery is not defined');
          return;
      }
      if (!config || !config.el) {
          return;
      }
      var _this = this,
          el = _this.$(config.el);

      if (!el || el.bindJdate) {
          return;
      }
      el.bindJdate = 1;
      _this.extend(config);
      _this.tap(el, function () {
          _this.show();
      });
      // 设置默认日期
      if (config.value) {
          if (el.nodeName.toLowerCase() == 'input') {
              el.value = config.value;
          } else {
              el.innerText = config.value;
          }
          var str = config.value.replace(/-/g, '/').replace(/[^\d/:\s]/g, ''),
              date = new Date(str);

          if (!date || date == 'Invalid Date') {
              console.error('Invalid Date:' + str);
          } else {
              el.bindDate = date;
          }
      }
  }
  Jdate.prototype = {
      constructor: Jdate,
      baseData: function baseData() {
          return {
              domId: {
                  YYYY: 'jdate-year',
                  MM: 'jdate-month',
                  DD: 'jdate-day',
                  hh: 'jdate-hour',
                  mm: 'jdate-min',
                  ss: 'jdate-sec'
              },
              opts: { //插件默认配置
                  el: '',
                  format: 'YYYY-MM-DD',
                  beginYear: 2000,
                  endYear: 2100,
                  init: null,
                  moveEnd: null,
                  confirm: null,
                  cancel: null,
                  minStep: 1,
                  trigger: 'tap',
                  lang: { title: '选择日期', cancel: '取消', confirm: '确认', year: '年', month: '月', day: '日', hour: '时', min: '分', sec: '秒' }
              }
          };
      },
      extend: function extend(config) {
          var _this = this,
              opts = _this.baseData().opts;

          for (var key in opts) {
              if (opts[key] && Object.prototype.toString.call(opts[key]) == '[object Object]') {
                  for (var key2 in config[key]) {
                      opts[key][key2] = config[key][key2] == undefined ? opts[key][key2] : config[key][key2];
                  }
              } else {
                  opts[key] = config[key] || opts[key];
              }
          }
          _this.config = opts;
      },
      createUI: function createUI() {
          var _this = this,
              data = _this.baseData(),
              config = _this.config,
              domId = data.domId,
              FormatArr = config.format.split(/-|\/|\s|:/g),
              len = FormatArr.length,
              ul = '',
              date = _this.$(config.el).bindDate || new Date(),
              itemClass = '',
              lang = config.lang;

          for (var i = 0; i < len; i++) {
              var f = FormatArr[i];

              ul += '<div id="' + domId[f] + '"><ul>';

              if (f == 'YYYY') {
                  for (var j = config.beginYear; j <= config.endYear; j++) {
                      itemClass = j == date.getFullYear() ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + j + lang.year + '</li>';
                  }
              } else if (f == 'MM') {
                  for (var k = 1; k <= 12; k++) {
                      itemClass = k == date.getMonth() + 1 ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + (k < 10 ? '0' + k : k) + lang.month + '</li>';
                  }
              } else if (f == 'DD') {
                  var day = _this.bissextile(date.getFullYear(), date.getMonth() + 1);
                  for (var l = 1; l <= day; l++) {
                      itemClass = l == date.getDate() ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + (l < 10 ? '0' + l : l) + lang.day + '</li>';
                  }
              } else if (f == 'hh') {
                  for (var m = 0; m <= 23; m++) {
                      itemClass = m == date.getHours() ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + (m < 10 ? '0' + m : m) + lang.hour + '</li>';
                  }
              } else if (f == 'mm') {
                  for (var n = 0; n <= 59; n += config.minStep) {
                      itemClass = n == date.getMinutes() ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + (n < 10 ? '0' + n : n) + lang.min + '</li>';
                  }
              } else if (f == 'ss') {
                  for (var o = 0; o <= 59; o++) {
                      itemClass = o == date.getSeconds() ? 'active' : '';

                      ul += '<li class="' + itemClass + '">' + (o < 10 ? '0' + o : o) + lang.sec + '</li>';
                  }
              }
              ul += '</ul></div>';
          }
          var $html = '<div class="jdate-mask"></div>\n            <div class="jdate-panel fadeIn">\n                <header>\n                    <span class="jdate-btn jdate-cancel">' + lang.cancel + '</span>\n                    ' + lang.title + '\n                    <span class="jdate-btn jdate-confirm">' + lang.confirm + '</span>\n                </header>\n                <section class="jdate-content">\n                    <div class="jdate-dim mask-top"></div>\n                    <div class="jdate-dim mask-bottom"></div>\n                    <div class="jdate-wrapper">\n                        ' + ul + '\n                    </div>\n                </section>\n            </div>',
              box = document.createElement("div");

          box.className = 'jdate-container';
          box.innerHTML = $html;
          document.body.appendChild(box);

          _this.scroll = {};

          for (var _i = 0; _i < len; _i++) {
              var $id = domId[FormatArr[_i]];

              _this.scroll[FormatArr[_i]] = $id;
              _this.slide($('#' + $id + '>ul'));
          }
          if (_this.scroll['mm'] && config.minStep != 1) {
              $('#' + _this.scroll['mm'] + ' li').eq(Math.round(date.getMinutes() / config.minStep)).addClass('active');
          }
          $('.jdate-container ul').each(function () {
              var that = $(this),
                  active = that.find('.active');

              if (!active.length) {
                  return;
              }
              var liTop = -active.position().top;
              that.animate({
                  top: liTop
              }, 0);
          });
      },
      eventType: function eventType() {
          var isTouch = "ontouchend" in document;

          return {
              isTouch: isTouch,
              tstart: isTouch ? "touchstart" : "mousedown",
              tmove: isTouch ? "touchmove" : "mousemove",
              tend: isTouch ? "touchend" : "mouseup",
              tcancel: isTouch ? "touchcancel" : "mouseleave"
          };
      },
      slide: function slide(el) {
          var _this = this,
              domId = _this.baseData().domId,
              lang = _this.config.lang;

          //滑动
          var T = void 0,
              mT = void 0,
              isPress = false,
              events = _this.eventType();

          el.bind(events.tstart, function (e) {
              e.stopPropagation();
              e.preventDefault();
              e = e.originalEvent;
              T = e.pageY || e.touches[0].pageY;
              if (!events.isTouch) {
                  isPress = true;
              }
          });
          el.bind(events.tmove, function (e) {
              var that = $(this);

              e.stopPropagation();
              e.preventDefault();
              e = e.originalEvent;

              if (!events.isTouch && !isPress) {
                  return false;
              }            mT = e.pageY || e.touches[0].pageY;
              that.css('top', that.position().top + (mT - T) + 'px');
              T = mT;
              if (that.position().top > 0) that.css('top', '0');
              if (that.position().top < -(that.height() - h)) that.css('top', '-' + (that.height() - h) + 'px');
          });
          el.bind(events.tend, function (e) {
              var that = $(this);

              e.stopPropagation();
              e.preventDefault();
              e = e.originalEvent;
              isPress = false;
              dragEnd(that);
          });
          el.bind(events.tcancel, function (e) {
              var that = $(this);

              e.stopPropagation();
              e.preventDefault();
              e = e.originalEvent;

              isPress = false;
              dragEnd(that);
          });

          function dragEnd(that) {
              //滚动调整
              var t = that.position().top;

              that.css('top', Math.round(t / h) * h + 'px');
              //定位active
              t = Math.round(Math.abs($(that).position().top));
              var li = that.children('li').get(t / h);
              $(li).addClass('active').siblings().removeClass('active');
              //修正天数
              if ([domId['YYYY'], domId['MM']].indexOf(that.parent().attr('id')) != -1 && _this.scroll['DD']) {
                  var year = $('#' + domId['YYYY'] + ' .active').text().replace(/\D/g, ''),
                      month = $('#' + domId['MM'] + ' .active').text().replace(/\D/g, '');

                  if (!year || !month) {
                      return;
                  }
                  var day = _this.bissextile(year, month);
                  if (day != $('#' + domId['DD'] + ' li').length) {
                      var active = $('#' + domId['DD'] + ' .active'),
                          d = active.text().replace(/\D/g, ''),
                          $html = '',
                          ul = $('#' + domId['DD'] + ' ul');

                      d > day && (d = day);

                      for (var l = 1; l <= day; l++) {
                          $html += '<li ' + (d == l ? 'class="active"' : '') + '>' + (l < 10 ? '0' + l : l) + lang.day + '</li>';
                      }
                      $('#' + domId['DD'] + ' ul').html($html);
                      if (Math.abs(ul.position().top) > ul.height() - h) ul.css('top', '-' + (ul.height() - h) + 'px');
                  }
              }
              if (_this.config.moveEnd) {
                  _this.config.moveEnd.call(_this);
              }
          }
      },
      $: function $(selector, flag) {
          if (typeof selector != 'string' && selector.nodeType) {
              return selector;
          }

          return flag ? document.querySelectorAll(selector) : document.querySelector(selector);
      },
      tap: function tap(el, fn) {
          var _this = this,
              hasTouch = "ontouchstart" in window;

          if (hasTouch && _this.config.trigger == 'tap') {
              var o = {};
              el.addEventListener('touchstart', function (e) {
                  var t = e.touches[0];

                  o.startX = t.pageX;
                  o.startY = t.pageY;
                  o.sTime = +new Date();
              });
              el.addEventListener('touchend', function (e) {
                  var t = e.changedTouches[0];

                  o.endX = t.pageX;
                  o.endY = t.pageY;
                  if (+new Date() - o.sTime < 300) {
                      if (Math.abs(o.endX - o.startX) + Math.abs(o.endY - o.startY) < 20) {
                          e.preventDefault();
                          fn.call(this, e);
                      }
                  }
                  o = {};
              });
          } else {
              el.addEventListener('click', function (e) {
                  fn.call(this, e);
              });
          }
      },
      show: function show() {
          var _this = this,
              config = _this.config,
              el = _this.$(config.el);

          if (!el.bindJdate) {
              return;
          }
          if (el.nodeName.toLowerCase() == 'input') {
              el.blur();
          }
          if (_this.$('.jdate-container')) {
              return;
          }
          if (config.init && config.init.call(_this) === false) {
              return;
          }

          _this.createUI();
          _this.event();
      },
      hide: function hide(flag) {
          var _this = this,
              el = _this.$('.jdate-panel.fadeIn');

          if (el) {
              el.className = 'jdate-panel fadeOut';
              _this.destroy(flag);
          }
      },
      event: function event() {
          var _this = this,
              mask = _this.$('.jdate-mask'),
              cancel = _this.$('.jdate-cancel'),
              confirm = _this.$('.jdate-confirm');

          _this.tap(mask, function () {
              _this.hide(1);
          });
          _this.tap(cancel, function () {
              _this.hide(1);
          });
          _this.tap(confirm, function () {
              var config = _this.config,
                  el = _this.$(config.el),
                  date = config.format,
                  newDate = new Date();

              for (var f in _this.scroll) {
                  var d = $('#' + _this.scroll[f] + ' .active').text().replace(/\D/g, '');

                  date = date.replace(f, d);
                  if (f == 'YYYY') {
                      newDate.setFullYear(d);
                  } else if (f == 'MM') {
                      newDate.setMonth(d - 1);
                  } else if (f == 'DD') {
                      newDate.setDate(d);
                  } else if (f == 'hh') {
                      newDate.setHours(d);
                  } else if (f == 'mm') {
                      newDate.setMinutes(d);
                  } else if (f == 'ss') {
                      newDate.setSeconds(d);
                  }
              }
              if (config.confirm) {
                  var flag = config.confirm.call(_this, date);
                  if (flag === false) {
                      return false;
                  } else if (flag) {
                      date = flag;
                  }
              }
              if (el.nodeName.toLowerCase() == 'input') {
                  el.value = date;
              } else {
                  el.innerText = date;
              }
              _this.hide();
              el.bindDate = newDate;
          });
      },
      bissextile: function bissextile(year, month) {
          var day = void 0;
          if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
              day = 31;
          } else if (month == 4 || month == 6 || month == 11 || month == 9) {
              day = 30;
          } else if (month == 2) {
              if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
                  //闰年
                  day = 29;
              } else {
                  day = 28;
              }
          }
          return day;
      },
      destroy: function destroy(flag) {
          var _this = this,
              config = _this.config;

          if (flag && config.cancel) {
              config.cancel.call(_this);
          }
          setTimeout(function () {
              var el = _this.$('.jdate-container');
              document.body.removeChild(el);
          }, 300);
      }
  };
  Jdate.version = version;

  return Jdate;

}));

效果:

 

posted @ 2019-11-01 10:35  一个小小前端  阅读(1040)  评论(0编辑  收藏  举报