rolldate-full
Version:
rolldate Multi-format, powerful mobile date selection plugin
326 lines (297 loc) • 13.3 kB
JavaScript
import './rolldate.less';
// 更换为iscroll4
import IScroll from './iscroll/iscroll';
let pkg = require('../package.json'),
iScroll = IScroll.iScroll;
export class Date{
constructor(config){
if(!config || !config.el){return;}
let _this = this,
el = _this.$(config.el)[0];
if(!el || el.rolldate){return;}
el.rolldate = true;
_this.extend(config);
el.addEventListener('click', function() {
let dom = _this.$('.rolldate-container')[0];
if(dom){return;}
if(el.nodeName == 'INPUT'){el.blur();}
if(_this.config.tapBefore && _this.config.tapBefore.call(_this,el) === false){return false;}
_this.createUi();
})
// 设置默认日期
if(config.value){
if(el.nodeName == 'INPUT'){
el.value = config.value;
}else{
el.innerText = config.value;
}
let str = config.value.replace(/-/g,'/').replace(/[^\d/:\s]/g,''),
date = new window.Date(str);
if(date == 'Invalid Date'){
console.error('无效的日期:'+str);
}else{
el.date = date;
}
}
}
baseData(){
return {
date:new window.Date(),
emptyli:'<li> </li>',
dateFormat:['YYYY-MM','YYYY-MM-DD','YYYY-MM-DD hh:mm','YYYY-MM-DD hh:mm:ss','YYYY','MM','DD','hh:mm','hh:mm:ss'],//支持的日期格式
domClass:['rolldate-year','rolldate-month','rolldate-day','rolldate-hour','rolldate-min','rolldate-sec'],
opts:{//插件默认配置
el:'',
format:'YYYY-MM-DD',
beginYear:2000,
endYear:2100,
theme:'',
scrollTime:200,
tapBefore:null,
moveEnd:null,
confirmBefore:null,
confirmEnd:null,
liHeight:40,
minStep:1
}
};
}
extend(config){
let _this = this,
opts = _this.baseData().opts;
for(let key in opts){
opts[key] = config[key] === 0? 0 : config[key] || opts[key];
}
_this.config = opts;
}
createUi(){
let _this = this,
data = _this.baseData(),
index = data.dateFormat.indexOf(_this.config.format);
index = index > 1? index+1 : index;
let $class = index == 5? [data.domClass[0]]: index ==6? [data.domClass[1]]: index ==7? [data.domClass[2]]: index ==8? data.domClass.slice(3,5): index ==9? data.domClass.slice(3):data.domClass.slice(0,index + 2),
len = $class.length,
ul = '',
el = _this.$(_this.config.el)[0],
date = el.date? el.date:data.date;
for(let i=0; i<len; i++){
ul += '<div id="'+ $class[i]+'"><ul>' + data.emptyli;
if(i == 0 && index < 6){
for(let j=_this.config.beginYear; j<=_this.config.endYear; j++){
ul += '<li'+(j==date.getFullYear()?' class="active"':'')+'>'+ j +'年</li>';
}
}else if((i == 1 || index == 6) && index < 7){
for(let k=1; k<=12; k++){
ul += '<li'+(k==date.getMonth() + 1?' class="active"':'')+'>'+ (k<10? '0'+k : k) +'月</li>';
}
}else if((i == 2 || index == 7) && index <= 7){
let day = _this.bissextile(date.getFullYear(),date.getMonth() + 1);
for(let l=1; l<=day; l++){
ul += '<li'+(l==date.getDate()?' class="active"':'')+'>'+ (l<10? '0'+l : l) +'日</li>';
}
}else if(i == 3 || (index > 7 && i == 0)){
for(let m=0; m<=23; m++){
ul += '<li'+(m==date.getHours()?' class="active"':'')+'>'+ (m<10? '0'+m : m) +'时</li>';
}
}else if(i == 4 || (index > 7 && i == 1)){
for(let n=0; n<=59; n+=_this.config.minStep){
ul += '<li'+(n==date.getMinutes()?' class="active"':'')+'>'+ (n<10? '0'+n : n) +'分</li>';
}
}else if(i == 5 || (index > 7 && i == 2)){
for(let o=0; o<=59; o++){
ul += '<li'+(o==date.getSeconds()?' class="active"':'')+'>'+ (o<10? '0'+o : o) +'秒</li>';
}
}
ul += data.emptyli +'</ul></div>'
}
let $html = `<div class="rolldate-mask"></div>
<div class="rolldate-wrapper">
<header>选择日期</header>
<section class="rolldate-content">
<div class="rolldate-frame">${ul}</div>
</section>
<footer>
<button class="rolldate-btn rolldate-cancel">取消</button>
<button class="rolldate-btn rolldate-confirm">确定</button>
</footer>
</div>`,
box = document.createElement("div"),
className = index == 0 || index == 8? 'rolldate-two':index == 3? 'rolldate-five':index == 4? 'rolldate-six':index >= 5 && index <= 7? 'rolldate-one':'',
scrollEnd = false;
box.className = 'rolldate-container ' + className;
box.innerHTML = $html;
document.body.appendChild(box);
_this.setTheme();
_this.iscroll = [];
_this.config.liHeight = document.querySelector('.rolldate-frame li').offsetHeight;
for(let i=0; i<len; i++){
_this.iscroll[i] = new iScroll($class[i], {
snap: 'li',
vScrollbar:false,
hScroll:false,
checkDOMChanges:i==2,
onScrollEnd:function(){
if(!scrollEnd){return;}
let liHeight = _this.config.liHeight;
if(Math.abs(this.y%liHeight) !== 0){
this.scrollTo(0, -Math.round(Math.abs(this.y)/liHeight)*liHeight, 0, false);
return false;
}
if(_this.config.moveEnd){
_this.config.moveEnd.call(_this,_this.$(_this.config.el)[0],this);
}
if(data.domClass.slice(0,2).indexOf(this.wrapper.id) != -1 && _this.iscroll[2]){
let prevDay = _this.getIscrollDay(_this.iscroll[2]),
day = _this.bissextile(_this.getIscrollDay(_this.iscroll[0]),_this.getIscrollDay(_this.iscroll[1])),
li = '';
if(day+2 != _this.$('#'+data.domClass[2]+' li').length){
for(let l=1; l<=day; l++){
li += '<li>'+ (l<10? '0'+l : l) +'日</li>';
}
li = data.emptyli + li + data.emptyli;
_this.$('#'+data.domClass[2]+' ul')[0].innerHTML = li;
if(prevDay > day){
_this.iscroll[2].scrollToElement(_this.$('#'+data.domClass[2]+' li')[day-1]);
}
}
}
}
});
let active = _this.$('#'+$class[i]+' .active')[0];
if(active){
_this.iscroll[i].scrollToElement(active.previousSibling,_this.config.scrollTime);
}
}
_this.event();
document.body.style.overflow = 'hidden';
setTimeout(function() {
scrollEnd = true;
}, 1000);
}
$(selector){
if(typeof selector != 'string' && selector.nodeType){
return [selector];
}
return document.querySelectorAll(selector);
}
event(){
let _this = this,
mask = _this.$('.rolldate-mask')[0],
cancel = _this.$('.rolldate-cancel')[0],
confirm = _this.$('.rolldate-confirm')[0];
mask.addEventListener('click', function(){_this.destroy(true);})
cancel.addEventListener('click', function(){_this.destroy(true);})
confirm.addEventListener('click', function(){
let el = _this.$(_this.config.el)[0],
data = _this.baseData(),
date = _this.config.format,
nativeDate = new window.Date(),
index = data.dateFormat.indexOf(date);
_this.iscroll.forEach(function(v,i){
let d = _this.getIscrollDay(v),
str;
if(index <=4){
str = i == 0? 'YYYY':i == 1? 'MM':i == 2? 'DD':i == 3? 'hh':i == 4? 'mm':'ss';
}else if(index == 5){
str = 'MM';
}else if(index == 6){
str = 'DD';
}else if(index == 7){
str = i == 0? 'hh':i == 1? 'mm':'';
}else if(index == 8){
str = i == 0? 'hh':i == 1? 'mm':'ss';
}
date = date.replace(str,d);
if(str == 'YYYY'){
nativeDate.setFullYear(d);
}else if(str == 'MM'){
nativeDate.setMonth(d-1);
}else if(str == 'DD'){
nativeDate.setDate(d);
}else if(str == 'hh'){
nativeDate.setHours(d);
}else if(str == 'mm'){
nativeDate.setMinutes(d);
}else if(str == 'ss'){
nativeDate.setSeconds(d);
}
})
if(_this.config.confirmBefore){
var flag = _this.config.confirmBefore.call(_this,el,date);
if(flag === false){
if(_this.config.confirmEnd){_this.config.confirmEnd.call(_this,el,date);}
return false
}else if(flag){
date = flag;
}
}
if(el.nodeName == 'INPUT'){
el.value = date;
}else{
el.innerText = date;
}
if(_this.config.confirmEnd){_this.config.confirmEnd.call(_this,el,date);}
_this.destroy();
el.date = nativeDate;
})
let liHeight = _this.config.liHeight;
_this.config.queryStyle = function(){
window.removeEventListener('resize',_this.config.queryStyle);
setTimeout(function() {
if(_this.$('.rolldate-container')[0] && liHeight != document.querySelector('.rolldate-frame li').offsetHeight){
_this.destroy(true);
}
}, 0);
};
window.addEventListener("resize", _this.config.queryStyle, false);
}
bissextile(year,month){
let day;
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(cancel){
let _this = this;
_this.iscroll.forEach(function(v,i){v.destroy();})
document.body.removeChild(_this.$('.rolldate-container')[0]);
if(cancel&&_this.config.confirmEnd){
let el = _this.$(_this.config.el)[0];
_this.config.confirmEnd.call(_this,el);
}
if(_this.config.queryStyle){
window.removeEventListener("resize", _this.config.queryStyle, false);
}
document.body.style.overflow = 'visible';
}
getIscrollDay(iscroll){
let _this = this,
liHeight = _this.config.liHeight,
index = Math.abs(iscroll.y%liHeight) !== 0?Math.round(Math.abs(iscroll.y)/liHeight)+1:Math.abs(iscroll.y)/liHeight+1;
return this.$('#'+iscroll.wrapper.id+' li')[index].innerText.replace(/\D/g,'');
}
setTheme(){
let _this = this,
theme = _this.config.theme,
defaultTheme = {blue:'#16a1d3',red:'#d91600',green:'#009688',black:'#393D49'},
header = _this.$('.rolldate-container header')[0],
btn = _this.$('.rolldate-container .rolldate-confirm')[0];
if(theme){
if(defaultTheme[theme]){
header.style.background = btn.style.background = defaultTheme[theme];
}else{
header.style.background = btn.style.background = theme;
}
}
}
}
export let version = pkg.version;