|
|
/**
|
|
|
* 时间范围滑块选择插件
|
|
|
* 基于 layui.slider 扩展的时间范围选择插件
|
|
|
*
|
|
|
* sliderTime.js License By momo
|
|
|
* V1.0 2021-04-19
|
|
|
*
|
|
|
*
|
|
|
* 使用说明:
|
|
|
* 1.sliderTime 基于 layui.slider,所以 slider 的配置都得以保留
|
|
|
* 2.range 参数强制为 true
|
|
|
* 3.新增 disabledValue 属性,禁止选择时间范围
|
|
|
* 例如:[[8:00, 10:00], [14:00, 15:00]]
|
|
|
* 4.新增 disabledText 属性,禁止选择时间范围被选中后的提示内容,不配置不显示提示
|
|
|
* 例如:'{start} - {end} 已占用',支持start和end时间占位符
|
|
|
* 5.新增 getValue 方法,返回当前选择的时间段(时间格式)
|
|
|
* 6.新增 isOccupation 方法,返回当前选择的时间段是否包含了禁止选择的时间段
|
|
|
* 7.新增 numToTime 公用方法,用于将十进制转为时间格式。例如:480 → 08:00
|
|
|
* 8.新增 timeToNum 公用方法,用于将时间格式转为十进制。例如:24:00 → 1440
|
|
|
*/
|
|
|
layui.define(['slider'], function (exports) {
|
|
|
"use strict";
|
|
|
var MOD_NAME = 'sliderTime',
|
|
|
$ = layui.jquery,
|
|
|
slider = layui.slider;
|
|
|
;
|
|
|
|
|
|
/**
|
|
|
* 外部接口
|
|
|
*/
|
|
|
var SliderTime = {
|
|
|
config: {}
|
|
|
/**
|
|
|
* 核心入口
|
|
|
*/
|
|
|
, render: function (options) {
|
|
|
var object = new Class(options);
|
|
|
return thisSliderTime.call(object);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 数字转时间格式
|
|
|
*/
|
|
|
, numToTime: function (value) {
|
|
|
var hours = Math.floor(value / 60);
|
|
|
var mins = (value - hours * 60);
|
|
|
return (hours < 10 ? "0" + hours : hours) + ":" + (mins < 10 ? "0" + mins : mins);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 时间转数字
|
|
|
*/
|
|
|
, timeToNum: function (value) {
|
|
|
var time = value.split(":");
|
|
|
return time[0] * 60 + parseInt(time[1]);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 构造器
|
|
|
*/
|
|
|
var Class = function (options) {
|
|
|
var that = this;
|
|
|
that.config = $.extend({}, SliderTime.config, options);
|
|
|
that.render();
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 操作当前实例
|
|
|
*/
|
|
|
var thisSliderTime = function () {
|
|
|
var that = this
|
|
|
, options = that.config;
|
|
|
|
|
|
return {
|
|
|
/**
|
|
|
* 设置时间段
|
|
|
*/
|
|
|
setValue: function (value, index) {
|
|
|
if (index !== 1) {
|
|
|
index = 0;
|
|
|
}
|
|
|
value = SliderTime.timeToNum(value);
|
|
|
var start, end, width,
|
|
|
$wrap = $(options.elem).find('.layui-slider-wrap'),
|
|
|
val = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
|
|
|
if (value === val[0] || value === val[1]) {
|
|
|
// 设置值等于当前最小或最大值,不移动
|
|
|
return;
|
|
|
} else if (value > val[1]) {
|
|
|
// 设置值大于当前最大值,移动后面圆点
|
|
|
val[1] > val[0] ? index = 1 : index = 0;
|
|
|
val[index] = value;
|
|
|
} else if (value < val[0]) {
|
|
|
// 设置值小于当前最小值,移动前面圆点
|
|
|
val[0] < val[1] ? index = 0 : index = 1;
|
|
|
val[index] = value;
|
|
|
} else {
|
|
|
// 设置值间与中间,则按照index移动
|
|
|
index === 0 ? val[0] = value : val[1] = value;
|
|
|
}
|
|
|
$wrap.eq(index).data("value", value);
|
|
|
|
|
|
start = (val[0] - options.min) / (options.max - options.min) * 100;
|
|
|
end = (val[1] - options.min) / (options.max - options.min) * 100;
|
|
|
// 设置圆点位置
|
|
|
if ("vertical" === options.type) {
|
|
|
$(options.elem).find('.layui-slider-wrap').eq(index).css("bottom", (index === 0 ? start : end) + '%');
|
|
|
} else {
|
|
|
$(options.elem).find('.layui-slider-wrap').eq(index).css("left", (index === 0 ? start : end) + '%');
|
|
|
}
|
|
|
// 设置滑动位置
|
|
|
width = Math.abs(end - start);
|
|
|
if ("vertical" === options.type) {
|
|
|
$(options.elem).find('.layui-slider-bar').css({
|
|
|
"height": width + '%',
|
|
|
"bottom": (start < end ? start : end) + '%'
|
|
|
});
|
|
|
} else {
|
|
|
$(options.elem).find('.layui-slider-bar').css({
|
|
|
"width": width + '%',
|
|
|
"left": (start < end ? start : end) + '%'
|
|
|
});
|
|
|
}
|
|
|
return;
|
|
|
// return that.slider.setValue(SliderTime.timeToNum(value), index)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取选中的时间段
|
|
|
*/
|
|
|
, getValue: function () {
|
|
|
var $wrap = $(options.elem).find('.layui-slider-wrap');
|
|
|
var value = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
|
|
|
//如果前面的圆点超过了后面的圆点值,则调换顺序
|
|
|
if (value[0] > value[1]) {
|
|
|
value.reverse();
|
|
|
}
|
|
|
return [SliderTime.numToTime(value[0]), SliderTime.numToTime(value[1])];
|
|
|
}
|
|
|
/**
|
|
|
* 选择的时间段是否包含被禁止选择的时间段
|
|
|
* 包含:返回禁止选择的时间段
|
|
|
* 不包含:false
|
|
|
*/
|
|
|
, isOccupation: function () {
|
|
|
if (options.disabledValue) {
|
|
|
var $wrap = $(options.elem).find('.layui-slider-wrap');
|
|
|
var value = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
|
|
|
//如果前面的圆点超过了后面的圆点值,则调换顺序
|
|
|
if (value[0] > value[1]) {
|
|
|
value.reverse();
|
|
|
}
|
|
|
for (var i in options.disabledValue) {
|
|
|
var date = options.disabledValue[i];
|
|
|
var min = SliderTime.timeToNum(date[0]);
|
|
|
var max = SliderTime.timeToNum(date[1]);
|
|
|
if (value[0] > min && value[0] < max
|
|
|
|| value[1] > min && value[1] < max
|
|
|
|| value[0] <= min && value[1] >= max) {
|
|
|
return date;
|
|
|
} else {
|
|
|
that.closeTips(options.elem);
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
} else {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
, config: options
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 滑块渲染
|
|
|
* @param options
|
|
|
*/
|
|
|
Class.prototype.render = function () {
|
|
|
var that = this
|
|
|
, options = that.config;
|
|
|
// 是否显示时刻,默认是
|
|
|
options.showstep = options.showstep == false ? false : true;
|
|
|
// 开启滑块的范围拖拽
|
|
|
options.range = true;
|
|
|
// 最小值,最小为0=0:00
|
|
|
options.min = options.min == undefined || SliderTime.timeToNum(options.min) < 0 ? 0 : SliderTime.timeToNum(options.min);
|
|
|
// 最大值,最大为1440=24*60=24:00
|
|
|
options.max = options.max == undefined || SliderTime.timeToNum(options.max) > 1440 ? 1440 : SliderTime.timeToNum(options.max);
|
|
|
//间隔值不能大于 max
|
|
|
options.step = options.step > options.max ? options.max : options.step;
|
|
|
// 初始值
|
|
|
options.value = typeof (options.value) == 'object' ? options.value : [SliderTime.numToTime(options.min), SliderTime.numToTime(options.min)];
|
|
|
options.value[0] = SliderTime.timeToNum(options.value[0]);
|
|
|
options.value[1] = SliderTime.timeToNum(options.value[1]);
|
|
|
|
|
|
// 初始化
|
|
|
that.slider = slider.render({
|
|
|
elem: options.elem
|
|
|
, type: options.type
|
|
|
, height: options.height
|
|
|
, theme: options.theme
|
|
|
, range: options.range
|
|
|
, showstep: options.showstep
|
|
|
, min: options.min
|
|
|
, max: options.max
|
|
|
, step: options.step
|
|
|
, value: options.value
|
|
|
, disabled: options.disabled
|
|
|
, setTips: function (value) {
|
|
|
value = SliderTime.numToTime(value);
|
|
|
if (options.setTips) {
|
|
|
return options.setTips(value);
|
|
|
} else {
|
|
|
return value;
|
|
|
}
|
|
|
}
|
|
|
, change: function (value) {
|
|
|
if (options.disabledValue && options.disabledText) {
|
|
|
// 当滑动到禁用时间范围时,自动提醒
|
|
|
for (var i in options.disabledValue) {
|
|
|
var date = options.disabledValue[i];
|
|
|
var min = SliderTime.timeToNum(date[0]);
|
|
|
var max = SliderTime.timeToNum(date[1]);
|
|
|
if (value[0] > min && value[0] < max
|
|
|
|| value[1] > min && value[1] < max
|
|
|
|| value[0] <= min && value[1] >= max) {
|
|
|
var disabledText = options.disabledText.replace('{start}', date[0]).replace('{end}', date[1])
|
|
|
that.showTips(options, disabledText)
|
|
|
break;
|
|
|
} else {
|
|
|
that.closeTips(options.elem);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (options.change) {
|
|
|
options.change(value);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 扩展元素
|
|
|
$(options.elem).find('.layui-slider')
|
|
|
// 开始结尾刻度时间
|
|
|
.append('<div class="step-start-num">' + SliderTime.numToTime(options.min) + '</div>')
|
|
|
.append('<div class="step-end-num">' + SliderTime.numToTime(options.max) + '</div>')
|
|
|
// 警告提示Tips
|
|
|
.append('<div class="slider-danger-tips"></div>');
|
|
|
if (options.showstep) {
|
|
|
// 开始结尾刻度标识
|
|
|
$(options.elem).find('.layui-slider')
|
|
|
.append('<div class="step-start-wrap"></div>')
|
|
|
.append('<div class="step-end-wrap"></div>');
|
|
|
}
|
|
|
|
|
|
|
|
|
// 定义整点和半点时刻标识
|
|
|
var $steps = $(options.elem).find('.layui-slider .layui-slider-step');
|
|
|
for (var i = 0, num = options.min; num <= options.max && i < $steps.length - 1; i++, num += options.step) {
|
|
|
if (that.numToMins(num) == 0 && i > 0) {
|
|
|
$steps.eq(i - 1).addClass('step-hour');
|
|
|
|
|
|
} else if (that.numToMins(num) == 30) {
|
|
|
$steps.eq(i - 1).addClass('step-half-hour');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 初始化选中禁止选择时间范围
|
|
|
if (options.disabledValue) {
|
|
|
options.disabledValue.forEach(function (date) {
|
|
|
var dateNum = [SliderTime.timeToNum(date[0]), SliderTime.timeToNum(date[1])];
|
|
|
|
|
|
var start = (dateNum[0] - options.min) / (options.max - options.min) * 100,
|
|
|
end = (dateNum[1] - options.min) / (options.max - options.min) * 100,
|
|
|
width = end - start;
|
|
|
var selectedSlider = '<div class="layui-slider-bar-selected layui-disabled" style=" ' + ("vertical" === options.type ? "height" : "width") + ':' + width + '%; ' + ("vertical" === options.type ? "bottom" : "left") + ':' + start + '% ;"></div>';
|
|
|
$(options.elem).find('.layui-slider-bar').after(selectedSlider);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 主题设置
|
|
|
if (options.theme) {
|
|
|
$(options.elem).find('.step-hour,.step-half-hour,.step-start-wrap,.step-end-wrap,.layui-slider-step').css("background", options.theme);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 数字转分钟
|
|
|
*/
|
|
|
Class.prototype.numToMins = function (value) {
|
|
|
var hours = Math.floor(value / 60);
|
|
|
var mins = (value - hours * 60);
|
|
|
return mins;
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 显示警告信息
|
|
|
*/
|
|
|
Class.prototype.showTips = function (options, text) {
|
|
|
if ("vertical" === options.type) {
|
|
|
$(options.elem).find('.slider-danger-tips').css({
|
|
|
"display": "block",
|
|
|
"bottom": $(options.elem).find('.layui-slider-tips')[0].style.bottom
|
|
|
}).text(text);
|
|
|
} else {
|
|
|
$(options.elem).find('.slider-danger-tips').css({
|
|
|
"display": "block",
|
|
|
"left": $(options.elem).find('.layui-slider-tips')[0].style.left
|
|
|
}).text(text);
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 关闭警告信息
|
|
|
*/
|
|
|
Class.prototype.closeTips = function (elem) {
|
|
|
$(elem).find('.slider-danger-tips').css({
|
|
|
"display": "none"
|
|
|
}).text('');
|
|
|
};
|
|
|
|
|
|
// 加载css
|
|
|
layui.link(layui.cache.base + 'sliderTime/sliderTime.css');
|
|
|
exports(MOD_NAME, SliderTime);
|
|
|
}); |