美文网首页
自定义 日历范围选择 jquery 插件 calendarRan

自定义 日历范围选择 jquery 插件 calendarRan

作者: sunxiaochuan | 来源:发表于2018-12-17 11:56 被阅读0次
  • 效果 Gif 图
calendarRange 日历范围选择插件.gif
  • 源码
// layout.less
/*375px布局*/
/*配合 js 计算的 rem 使用具体换算设计稿的 20px = 20 / @layremvalue*/
@layremvalue: 100rem;
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html {
  font-size: calc(100vw / 7.5);
}
body {
  font-size: 0.28rem;
  font-family: 'Helvetica Neue', Helvetica, Arial, 'PingFang SC',
    'Hiragino Sans GB', 'Heiti SC', 'Microsoft YaHei', 'WenQuanYi Micro Hei',
    sans-serif;
  -webkit-text-size-adjust: none;
  -moz-text-size-adjust: none;
  -ms-text-size-adjust: none;
  text-size-adjust: none;
  padding: 0;
  margin: 0 auto;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* 取消链接高亮 */
  background-color: #f1f5fb;
}
h1,
h2,
h3,
h4,
h5 {
  font-weight: normal;
}
a {
  text-decoration: none;
  color: inherit;
}
// 公用容器
.mainbox {
  padding-bottom: 98 / @layremvalue;
  overflow-y: auto;
}
/*文本单行溢出隐藏*/
.txtoneline {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/*文本多行溢出隐藏  -webkit-line-clamp: 2; 溢出行数*/
.txtmorline {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
/*表单元素统一初始化样式*/
input,
select,
button {
  -webkit-appearance: none; /*去除阴影*/
  border: 0;
  outline: 0;
  background-color: transparent;
}
.checkbox {
  -webkit-appearance: checkbox;
}
input[type='checkbox'] {
  -webkit-appearance: checkbox;
}

/*input palceholder 样式自定义*/
/* 使用webkit内核的浏览器 */
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
  color: #999;
}
/* Firefox版本4-18 */
input::-moz-placeholder,
textarea::-webkit-input-placeholder {
  color: #999;
}
/* Firefox版本19+ */
input:-ms-input-placeholder,
textarea::-webkit-input-placeholder {
  color: #999;
}
/*清除浮动*/
.clearfix:after {
  content: ' ';
  display: block;
  height: 0;
  clear: both;
}
.clearfix {
  *zoom: 1;
} /*IE6/7*/
/* 弹窗专用 禁止滚轮 滚动*/
.scrollnone {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: fixed;
  max-width: 640px;
  min-width: 320px;
  left: 0;
  right: 0;
  margin: auto;
}
// link 右箭头
.link-arrow-right {
  position: relative;
  &::before {
    content: '';
    display: block;
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    background: url(../img/sales/icon-rightarrow.png) center center no-repeat;
    width: 18 / @layremvalue;
    height: 30 /@layremvalue;
    background-size: 18 / @layremvalue 30 /@layremvalue;
  }
}


// calendarRange.less
@import '/css/layout.css';
/*配合 js 计算的 rem 使用具体换算设计稿的 20px = 20 / @layremvalue*/
@layremvalue: 100rem;
// 日历范围插件样式表
@activeColor: #4289fe;
@middleColor: #ecf3fe;

[id*='id'],
[id^='id'] {
  height: (48 + 725 + 88) / @layremvalue;
}
.calendar-range {
  text-align: center;
  color: #2e4052;
  font-size: 32 / @layremvalue;
  position: relative;
  background-color: #fff;
  max-height: (48 + 725 + 88) / @layremvalue;
  .color-blue {
    color: @activeColor;
  }
  .calendar-week {
    display: flex;
    height: 48 / @layremvalue;
    .week-text {
      font-size: 24 / @layremvalue;
      flex: 100 / 7;
      line-height: 48 / @layremvalue;
      background-color: #fafafa;
    }
  }
  .calendar-scroll {
    overflow-y: auto;
    max-height: 725/@layremvalue;
    .scroll-content {
      padding: 15 / @layremvalue 0 0;
      div {
        float: left;
      }
      .content-title {
        width: 100%;
        line-height: 50 / @layremvalue;
        height: 50 / @layremvalue;
        color: #000000;
        font-size: 32 / @layremvalue;
      }
      .content-item {
        width: 100 / 7%;
        height: 112 / @layremvalue;
        line-height: 50 / @layremvalue;
        padding: 6 / @layremvalue 0;
        transition: all .2s;
        &-start,
        &-end {
          background-color: @activeColor;
          color: #fff;
          border-radius: 8 / @layremvalue;
          position: relative;
          &::before {
            content: '';
            display: block;
            position: absolute;
            left: 0;
            right: 0;
            bottom: 6 / @layremvalue;
            font-size: 24 / @layremvalue;
          }
        }
        &-start {
          &::before {
            content: '开始';
          }
        }
        &-end {
          &::before {
            content: '结束';
          }
        }
        &-middle {
          background-color: @middleColor;
        }
      }
    }
  }
  .calendar-btn {
    height: 88 / @layremvalue;
    line-height: 88 / @layremvalue;
    display: flex;
    justify-content: center;
    box-shadow: 0 1px 0 0 #ddd inset;
    div {
      flex: 50%;
    }
    .reset-btn {
      color: #2e4052;
    }
    .confirm-btn {
      color: #fff;
      background-color: @activeColor;
    }
  }
}

// 自定义日历范围选择组件(倒数的时间段) sunxc 2018.12.15
;(function($) {
  var calendarRange = (function() {
    /**
     * 插件函数
     * @param {dom} element 插件追加dom容器对象
     * @param {object} options 插件配置对象
     *
     */
    function calendarRange(element, options) {
      // calendar容器dom
      this.element = element
      // 合并插件配置 defaults + options
      this.options = $.extend(true, $.fn.calendarRange.defaults, options || {})
      // 插件初始化
      this.init()
    }
    calendarRange.prototype = {
      init: function() {
        // 初始化插件 dom + 事件
        var me = this
        // 展示月的个数 强制转换为 12 避免出现 bug
        me.manyMonths = me.options.manyMonths > 12 ? 12 : me.options.manyMonths
        // 确定按钮
        me.calendarConfirmBtn = me.options.calendarConfirmBtn
        // 重置按钮
        me.calendarResetBtn = me.options.calendarResetBtn

        // dom
        // 开始
        var html = `<div class="calendar-range" id="calendarDom">
            <input id="calendarStartDate" type="hidden" value=""/>
            <input id="calendarEndDate" type="hidden" value=""/>
            <div class="calendar-week">
                <div class="week-text color-blue">日</div>
                <div class="week-text">一</div>
                <div class="week-text">二</div>
                <div class="week-text">三</div>
                <div class="week-text">四</div>
                <div class="week-text">五</div>
                <div class="week-text color-blue">六</div>
            </div>
            <div class="calendar-scroll">
                <div class="scroll-content clearfix">`
        // 日期拼接
        /**
         * 生成日期 html
         * @param {number || string} manyMonths 月份的个数
         */
        function creationDateList(manyMonths) {
          let htmlStr = ''
          var now = me.options.calendarStartDate
            ? new Date(me.options.calendarStartDate)
            : new Date()
          // 当前的年 月
          var year = now.getFullYear()
          var month = now.getMonth() + 1
          // 根据月的数量循环生成 html
          for (let i = 0; i < me.manyMonths; i++) {
            // 如果是只要一个月的数据便不做过多的加减判断
            if (me.manyMonths != 1) {
              // 非首次循环自加1,否则得出需要展示的最小的月份,正排
              if (i != 0) {
                month++
                // 判断月份转换年和月
                if (month < 1) {
                  month = month - i + 12 + 1
                  month = month > 12 ? 12 : month
                  year -= 1
                } else if (month > 12) {
                  month -= 12
                  month = month === 0 ? 1 : month
                  year++
                }
              } else {
                month -= me.manyMonths - 1
                // 判断月份转换年和月
                if (month < 1) {
                  month += 12
                  month = month > 12 ? 12 : month
                  year--
                } else if (month > 12) {
                  month -= 12
                  month = month === 0 ? 1 : month
                  year++
                }
              }
            }
            // 月份数组
            let monthsArray = null
            if (me._isLeapYear(year)) {
              monthsArray = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            } else {
              monthsArray = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            }
            htmlStr += `<div class="content-title">${year}年${month}月</div>`
            for (let x = 0; x < monthsArray[month - 1]; x++) {
              let week = new Date(`${year}/${month}/${x + 1}`).getDay()
              // 月份首日判断:是周几就 margin-left 几个 content-item 的距离
              if (x === 0) {
                htmlStr += `<div class="content-item ${
                  week === 0 || week === 6 ? 'color-blue' : ''
                }" data-date="${year}/${month}/${x +
                  1}" style="margin-left:${(100 / 7) * week}%;">${x + 1}</div>`
              } else {
                htmlStr += `<div class="content-item ${
                  week === 0 || week === 6 ? 'color-blue' : ''
                }" data-date="${year}/${month}/${x + 1}">${x + 1}</div>`
              }
            }
          }
          return htmlStr
        }
        html += creationDateList(me.manyMonths)
        // 结束
        html += `</div>
                </div>
                <div class="calendar-btn">
                    <div class="reset-btn" id="calendarResetBtn">重置</div>
                    <div class="confirm-btn" id="calendarConfirmBtn">确定</div>
                </div>
            </div>`

        me.element.append(html)
        // 日期点击事件
        $('body').on('click', '#calendarDom .content-item', function(e) {
          me._clickHandle(e)
        })
        // 重置 按钮点击事件
        $('body').on('click', '#calendarResetBtn', function() {
          me._resetTimeData()
        })
        // 确定 按钮点击事件
        // $start, $end
        $('body').on('click', '#calendarConfirmBtn', function() {
          const $start = $('#calendarStartDate').val()
          const $end = $('#calendarEndDate').val()
          if ($start && $end) {
            // 提交数据事件
            me.options.callback($start, $end)
          }
        })
      },
      /**
       *
       * @param {number} year 是否是闰年
       */
      _isLeapYear: function(year) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
      },
      /**
       * 每个小日期的点击事件
       * @param {object} e 点击的 dom 元素
       */
      _clickHandle: function(e) {
        const me = this
        const $this = $(e.target)
        const index = $this.index()
        const $calendarStartDate = $('#calendarStartDate')
        const $calendarEndDate = $('#calendarEndDate')
        // 已经点击了两次
        if ($calendarStartDate.val() && $calendarEndDate.val()) {
          // 清空数据重新执行
          me._resetTimeData()
          me._clickHandle(e)
        } else if ($calendarStartDate.val()) {
          // 之前已经点击了一次开始
          const startIndex = $('#calendarDom')
            .find('.content-item-start')
            .index()
          // 判断当前的索引值如果小于之前点击的索引值,将当前点击的重置为开始点击的
          if (index < startIndex) {
            $this
              .addClass('content-item-start')
              .siblings()
              .removeClass('content-item-start')
            $calendarStartDate.val($this.attr('data-date'))
          } else {
            $this.addClass('content-item-end')
            $calendarEndDate.val($this.attr('data-date'))
          }
        } else {
          //从未点击过
          $this.addClass('content-item-start')
          $calendarStartDate.val($this.attr('data-date'))
        }
      },
      /**
       * 重置数据事件
       * @param {object} $this 点击的 dom 元素
       */
      _resetTimeData: function($this) {
        $this = $this || $('#calendarDom .content-item')
        const $calendarStartDate = $('#calendarStartDate')
        const $calendarEndDate = $('#calendarEndDate')
        $calendarStartDate.val('')
        $calendarEndDate.val('')
        $this
          .siblings()
          .removeClass('content-item-start')
          .removeClass('content-item-end')
      }
    }

    return calendarRange
  })()

  $.fn.calendarRange = function(options) {
    return this.each(function() {
      var me = $(this)
      // 获取实例
      var instance = me.data('calendarRange')
      // 判断:实例如果未创建,创建实例
      if (!instance) {
        me.data('calendarRange', (instance = new calendarRange(me, options)))
      }

      if ($.type(options) === 'string') return instance[options]()
    })
  }
  $.fn.calendarRange.defaults = {
    // 指定开始的日期 yyyy/mm/dd
    calendarStartDate: '',
    //展示的之前月份个数 默认为 3,最大为 12,大于 12 会强制转换为 12 避免出现 bug
    manyMonths: 3,
    /**
     * 回调函数 主要是为了提交数据用的
     * @param {date} $start 开始时间
     * @param {date} $end 结束时间
     */
    callback: function($start, $end) {
      console.log($start, $end)
    }
  }
})($)
// // 测试语法
// $('#id1').calendarRange({
//   calendarStartDate: '2008/2/2',
//   manyMonths: 12,
//   callback: function($start,$end) {
//     console.log(`start:${$start}\nend:${$end}`)
//   }
// })

  • 使用方法
// 示例代码
// 测试语法 可配置的 options 参数,不写便是默认的
$('#id1').calendarRange({
  calendarStartDate: '2008/2/2',
  manyMonths: 20,
  callback: function($start,$end) {
    console.log(`start:${$start}\nend:${$end}`)
  }
})

相关文章

网友评论

      本文标题:自定义 日历范围选择 jquery 插件 calendarRan

      本文链接:https://www.haomeiwen.com/subject/aauqkqtx.html