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}`)
}
})
网友评论