s94-inputdate
Version:
时间选择控件
312 lines (296 loc) • 13.9 kB
JavaScript
/**
* 时间选择控件
* inputdate(fmt,initdate,callback);
* fmt 返回的时间字符串格式样式,YMDHIS分别表示年月日时分秒,大写为有前置0、小写为没有前置0;W为中文的星期几、w为星期序列(0为星期天,1为星期一...)。默认为Y-M-D H:I:S
* initdate 初始化时间,字符串,格式和fmt一致,默认为当前时间(new Date()).getTime()
* callback 回调函数,传入一个对象,包含属性[y,m,d,h,i,s,strtime]
* **如果引入有jQuery,还有jQuery扩展
* $().inputdate(fmt,callback);
* 如果操作的DOM对象有value属性(如input标签),那么“初始化时间”对象的value,且选择和会自动修改value属性
*/
(function(){
"use strict";
var IDNAME = 's94_inputdate'+(new Date()).getTime();
var FUN_PREFIX = IDNAME+'_';
var now_type='d';//当前选择类型
var has = {d:0,m:0,y:0,t:0},
now = {y:0,m:0,d:0,h:0,i:0,s:0}; //当前时间,包含属性[y,m,d,h,i,s]
var doms={};
function init_type(){
for (var k in has) {
if(has[k]) return k;
}
}
/**
* 插入时间的控件inputdate(callback[, fmt, initdate])
* @param {Object} callback 回调函数
* @param {Object} fmt 【可选】返回的时间字符串格式样式,默认为Y-M-D H:I:S
* @param {Object} initdate 【可选】初始化时间,Date|String,为字符串要求格式和fmt一致,默认为当前时间
*/
function inputdate(callback, fmt, initdate){
if(!inputdate.container) inputdate.init();
inputdate.fmt = fmt = fmt || 'Y-M-D H:I:S';
has.y = /(^|[^\\])y/i.test(fmt);
has.m = /(^|[^\\])m/i.test(fmt);
has.d = /(^|[^\\])(d|w)/i.test(fmt);
has.t = /(^|[^\\])(h|i|s)/i.test(fmt);
if(!has.y&&!has.m&&!has.d&&!has.t) throw new Error('时间字符串格式错误');
if (initdate) {
var t = initdate instanceof Date ? initdate : $.strtodate(initdate, fmt);
} else {
var t = new Date();
t.setMilliseconds(0);
if(!has.t) {
t.setHours(0);
t.setMinutes(0);
t.setSeconds(0);
}
}
now.y = t.getFullYear();
now.m = t.getMonth() + 1;
now.d = t.getDate();
now.h = t.getHours();
now.i = t.getMinutes();
now.s = t.getSeconds();
now_type = init_type();
inputdate.callback = callback;
var rem = $.rem.get();
var vw = document.documentElement.clientWidth, vh = document.documentElement.clientHeight;
var mw = 3*rem, mh = 4*rem;
if(vw > 7.5*rem && vh > 6*rem && window.event){
var sty={}, exy = $.eventOffsetScreen();
if (exy.x!==undefined && exy.y!==undefined) {
sty['position'] = 'absolute';
sty['left'] = (vw-exy.x > mw ? exy.x : exy.x-mw)+'px';
sty['top'] = (vh-exy.y > mh ? exy.y : vh-mh)+'px';
};
$(doms.body).css(sty);
}else{
$(doms.body).attr('style','');
}
$(inputdate.container).css('font-size',rem+'px').show();
display();
}
inputdate.init = function(config){
var SETUP = {
color: '#307cc4',
week: ['日','一','二','三','四','五','六'],
month: ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'],
img_left2: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAS1BMVEVMaXH///////////////////////////////////////////////////////////////////////////////////////////////9UrLx+AAAAGHRSTlMAIfUd6vsyJPkXJvQtEin3Ou/nbUimeQWjo8UCAAAAt0lEQVR42r3Qyw6EIAwFUORZAUXUce7/f+kMj8QFdTnTzU160oYi/lnr8e65MLpoHDV3XKPOGbBNcQ6q9K12nNUwsSWv9Kwqw9iuG6eougORfXOsl7Gq2c239s2cbgCpbzoDODHUCYTyxRZIsxhrkkiujBNo5TwgVE+QD06+ZEZyjHsCTW0+KcZX6vsJ6WF/dm2P9Iy7gKD6POc+tL4LzPv63aU/JZht0No/SiqJSzB1vlTPKH5dH/87DEZvAY7FAAAAAElFTkSuQmCC',
img_left: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAS1BMVEVMaXH///////////////////////////////////////////////////////////////////////////////////////////////9UrLx+AAAAGHRSTlMANcejjJVVRpo+pe1LIPZbd4G66S+2rSmsbrQsAAAAXElEQVR42s3MWQ5AQBRE0Uej2zxz979SK3glkRD396TKvm7MlFbkUpl8jTD7WkPxVDMofd0g+XoOBF/7gUNoy25+LbmJStaovIBO7u9d/qf3vVYe0N6Ayf1if+gCodcFK+0LnW4AAAAASUVORK5CYII=',
};
config = $.merge(SETUP, config);
var html = '<style type="text/css">';
html += '#'+IDNAME+'{display: flex;justify-content: center;align-items: center;position: fixed;left: 0;top: 0;width: 100%;height: 100%;color: #333;z-index: 999999999;}\n';
html += '#'+IDNAME+' *{box-sizing: border-box;margin: 0;padding: 0;-webkit-tap-highlight-color: rgba(0,0,0,0);}\n';
html += '#'+IDNAME+' li{list-style: none;}\n';
html += '#'+IDNAME+' span{font-size: 0.2em;line-height: 1.5;user-select: none;display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;cursor: pointer;}\n';
html += '#'+IDNAME+'>p{position: absolute;left: 0;top: 0;width: 100%;height: 100%;z-index: 0;}\n';
html += '#'+IDNAME+'>div{background: #fff;width: 3em;font-size: 1em;position: relative;z-index: 2;box-shadow: 0 0 0.04em 0 '+config.color+';}\n';
html += '#'+IDNAME+'>div>header{display: flex;border-bottom: 1px solid #e2e2e2;height: 0.6em;margin-bottom: 0.1em;background: '+config.color+';color: #fff;justify-content: space-between;align-items: center;}\n';
html += '#'+IDNAME+'>div>header>*{display: block;width: 0.3em;height: 0.3em;margin:0 0.05em;cursor: pointer;background-size: 100%;}\n';
html += '#'+IDNAME+'>div>header>b{background-image: url('+config.img_left2+');}\n';
html += '#'+IDNAME+'>div>header>i{background-image: url('+config.img_left+');}\n';
html += '#'+IDNAME+'>div>header>b[back],#'+IDNAME+'>div>header>i[back]{transform: rotate(180deg);}\n';
html += '#'+IDNAME+'>div>header>div{color: #fff;flex-grow: 2;}\n';
html += '#'+IDNAME+'>div>ul{display: flex;flex-wrap: wrap;justify-content: space-around;overflow: hidden;padding: 0 0.05em;}\n';
html += '#'+IDNAME+'>div>ul>*{width: 0.9em;height: 0.37em;}';
html += '#'+IDNAME+'>div>ul li:hover{background-color: #eaeaea;}\n';
html += '#'+IDNAME+'>div>ul li.on{background-color: '+config.color+';color: #fff;}\n';
html += '#'+IDNAME+'>div>ul[type="day"]>li{width: 0.4em;}\n';
html += '#'+IDNAME+'>div>ul[type="month"]>li{margin: 0.14em 0;}\n';
html += '#'+IDNAME+'>div>ul[type="year"]>li{margin: 0.07em 0;}\n';
html += '#'+IDNAME+'>div>ul>ol{position: relative;border: 1px solid #e2e2e2;height: 2.2em;cursor: default;overflow-y: scroll;}\n';
html += '#'+IDNAME+'>div>ul>ol::-webkit-scrollbar {display: none;}';
html += '#'+IDNAME+'>div>ul>ol>li{width: 100%;height: 0.0.37em;margin: 0.06em 0;}';
html += '#'+IDNAME+'>div>footer{background: #fff;display: flex;border-top: 1px solid #e2e2e2;height: 0.6em;margin-top: 0.1em;padding: 0 0.1em;justify-content: space-between;align-items: center;}\n';
html += '#'+IDNAME+'>div>footer>*{display: flex;}\n';
html += '#'+IDNAME+'>div>footer>ol>li{border: 1px solid #C9C9C9;border-radius: 0.04em;margin: 0 0.01em;padding: 0 0.05em;}\n';
html += '#'+IDNAME+'>div[type="y"]>header>i,#'+IDNAME+'>div[type="m"]>header>i,#'+IDNAME+'>div[type="t"]>header>b,#'+IDNAME+'>div[type="t"]>header>i{display: none;}\n';
html += '</style><p onclick="$(this).parent().hide()"></p><div type="day">';
html += '<header><b onclick="'+FUN_PREFIX+'change_year()"></b><i onclick="'+FUN_PREFIX+'change_month()"></i><div></div><i onclick="'+FUN_PREFIX+'change_month(1)" back></i><b onclick="'+FUN_PREFIX+'change_year(1)" back></b></header>';
html+='<ul type="year" style="display: none;">';
for (var i=0;i<15;i++) {
html+='<li data=""><span></span></li>';
}
html+='</ul><ul type="month" style="display: none;">';
for (i=0;i<12;i++) {
html+='<li data="'+(i+1)+'"><span>'+config.month[i]+'</span></li>';
}
html += '</ul><ul type="day" style="display: none;">';
for (var i=0;i<7;i++) {
html+='<li><span>'+config.week[i]+'</span></li>';
}
for (var i=0;i<31;i++) {
html+='<li data="'+(i+1)+'"><span>'+(i+1)+'</span></li>';
}
html+='</ul><ul type="time" style="display: none;"><p><span>时</span></p><p><span>分</span></p><p><span>秒</span></p><ol type="h">';
for (i=0;i<24;i++) {
html+='<li data="'+i+'"><span>'+(i<10?'0'+i:i)+'</span></li>';
}
html+='</ol><ol type="i">';
for (i=0;i<60;i++) {
html+='<li data="'+i+'"><span>'+(i<10?'0'+i:i)+'</span></li>';
}
html+='</ol><ol type="s">';
for (i=0;i<60;i++) {
html+='<li data="'+i+'"><span>'+(i<10?'0'+i:i)+'</span></li>';
}
html+='</ol></ul><footer><p></p><ol><li onclick="'+FUN_PREFIX+'clear()"><span>清空</span></li><li onclick="'+FUN_PREFIX+'now()"><span>现在</span></li><li onclick="'+FUN_PREFIX+'ok()"><span>确定</span></li></ol></footer></div>';
if(!inputdate.container){
inputdate.container = document.createElement('div');
inputdate.container.id = IDNAME;
document.documentElement.appendChild(inputdate.container);
}
inputdate.container.style.display = 'none';
inputdate.container.innerHTML = html;
doms.body = document.querySelector('#'+IDNAME+'>div');
doms.title = doms.body.querySelector('header>div');
doms.footer = doms.body.querySelector('footer>p');
doms.y = doms.body.querySelector('ul[type="year"]');
doms.m = doms.body.querySelector('ul[type="month"]');
doms.d = doms.body.querySelector('ul[type="day"]');
doms.t = doms.body.querySelector('ul[type="time"]');
$('#'+IDNAME+' li[data]').on('click',function(){
$(this).parent().find('li').removeClass('on');
var v = $(this).addClass('on').attr('data')*1;
if(now_type=='t'){
now[$(this).parent().attr('type')] = v;
}else{
now[now_type] = v;
var ks = ['y','m','d','t'];
for (var i = ks.indexOf(now_type)+1; i < 4; i++) {
if(has[ks[i]]) return display(ks[i]);
}
close();
}
})
//全局方法
window[FUN_PREFIX+'change_year'] = function(add){
if (add) {
now.y += (now_type=='y' ? 15 : 1);
} else{
now.y -= (now_type=='y' ? 15 : 1);
}
display(now_type);
}
window[FUN_PREFIX+'change_month'] = function(add){
add ? (now.m++) : (now.m--);
if(now.m > 12){
now.y++;now.m=1;
}
if(now.m < 1){
now.y--;now.m=12;
}
display(now_type);
}
window[FUN_PREFIX+'display'] = display;
window[FUN_PREFIX+'clear'] = function(){
close(false);
}
window[FUN_PREFIX+'now'] = function(){
var t = new Date();
now={
y: t.getFullYear(),
m: t.getMonth() + 1,
d: t.getDate(),
h: t.getHours(),
i: t.getMinutes(),
s: t.getSeconds(),
}
display(now_type);
}
window[FUN_PREFIX+'ok'] = function(){
close();
}
}
/*计算指定月份多少天*/
function day_num_month(y,m){
var isRun = !((y%100) ? (y%4) : (y%400));
return m==2?(isRun?29:28):(m==4||m==6||m==9||m==11?30:31)
}
function display(type){
now_type = type || init_type();
$(doms.body).attr('type',now_type);
$('#'+IDNAME+'>div>ul').hide();
$(doms[now_type]).show().find('li.on').removeClass('on');
display[now_type]();
if(now_type=='t'){
$(doms.footer).html((has.d||has.y||has.m) ? '<span onclick="'+FUN_PREFIX+'display()">选择日期</span>' : '');
}else{
$(doms.footer).html(has.t ? '<span onclick="'+FUN_PREFIX+'display(\'t\')">'+now.h+' : '+now.i+' : '+now.s+'</span>':'');
}
}
display.y = function(){
var num = 15;
var start = now.y - (now.y)%num;
$(doms.title).html('<span>'+start+'年~'+(start+num-1)+'年</span>');
$(doms.y).find('li').each(function(){
if(start==now.y) $(this).addClass('on');
$(this).attr('data', start).html('<span>'+start+'年</span>');start++;
})
}
display.m = function(){
$(doms.title).html('<span onclick="'+FUN_PREFIX+'display(\'y\')">'+now.y+'年</span>');
$(doms.m).find('li').eq(now.m-1).addClass('on');
}
display.d = function(){
$(doms.title).html('<span><font onclick="'+FUN_PREFIX+'display(\'y\')">'+now.y+'年</font> <font onclick="'+FUN_PREFIX+'display(\'m\')">'+now.m+'月</font></span>');
//渲染选择日期
$(doms.d).find('li[empty]').remove();
var html = '',i;
var day_num = day_num_month(now.y, now.m);//当前月有多少天
var first_day_w = (new Date(now.y+'/'+now.m+'/1')).getDay(); //当前月的第一天是星期几
var $days = $(doms.d).find('li');
for(i=27; i<31; i++) {
i<day_num ? $days.eq(i+7).show() : $days.eq(i+7).hide();
}
$days.eq(now.d+6).addClass('on');
for(i=0,html=''; i<first_day_w; i++){
html += '<li empty></li>';
}
$days.eq(6).after(html);
for(i+=day_num,html=''; i<42; i++){
html += '<li empty></li>';
}
$(doms.d).append(html);
}
display.t = function(){
$(doms.title).html('<span>选择时间</span>');
var ks = ['h','i','s'];
$(doms.t).find('ol').each(function(dom, i){
var on = this.querySelectorAll('li')[now[ks[i]]];
$(on).addClass('on');
this.scrollTop = on.offsetTop-(this.offsetHeight/2);
})
}
display.i = function(){
$(doms.title).html('<span>分</span>');
$(doms.i).find('li').eq(now.i).addClass('on');
}
display.s = function(){
$(doms.title).html('<span>秒</span>');
$(doms.s).find('li').eq(now.s).addClass('on');
}
function close(ac){
var res={
value: '',
valueOf: function(){return this.value},
toString: function(){return this.value},
y:0,m:0,d:0,h:0,i:0,s:0,w:0,
Date:null,
};
$('.datetime-outer').hide();
if (ac!==false) {
for (var k in now) {
res[k] = now[k];
}
res.Date = new Date(res.y, res.m-1, res.d, res.h, res.i, res.s),
res.w = res.Date.getDay();
res.value = $.date(inputdate.fmt, res.Date);
}
typeof(inputdate.callback)=="function" && inputdate.callback(res);
$('#'+IDNAME).hide();
}
module.exports = inputdate;
})(require('s94-web'));