时间选择框

来源:互联网 发布:js解决跨域问题 编辑:程序博客网 时间:2024/06/03 09:18

想必有很多的道友都使用过时间插件,各种各样的很多,今天给大家分享一个,自己写的一个时间小插件,不在样式有多绚,主要和大家分享一下心得,按惯例先上效果图:


恩,就是这个样子(样式就不说了 根据自己的需求定样式就行了 ),调用很简单:

Array.prototype.forEach.call(document.querySelectorAll(".date-input"),//一次调用多个function(item){new MyDate(item,{//初始化的对象 itemtype: "-",//y-m-d type 链接方式 可以不写complete: true//为true时显示 小时分钟  默认为false})})
然后就是我们的 js 代码 ( 具体说明在注释里面 ):

;(function(win,doc,_undefined){var MyDate;MyDate = (function(){function MyDate(obj,option){this._obj = obj || '',//这里就是我们的input 对象this._type = option&&option.type || "-",//年月日连接类型this._complete = option&&option.complete || false,//是否显示小时 分钟this._pNode = '',//this._dom的父元素this._dom = '',//date-container  日历的盒子元素this._cyear = '',this._cmonth = '',this._cday = '',this._yearNode = '',//展示 年份 的node 下面同理this._monthNode = '',this._daysNode = '',this._hourNode = '',this._msNode = '',this._selectTimer = '';//选着好的数据  可以储存在这里  可以根据this._complete是否显示时间this.init();//日历初始化}return MyDate.prototype.init = function(){/** * * 模式: 通用的工厂+原型的模式 * */var _obj = this._obj;if(!_obj || _obj.nodeType !== 1) throw new Error("传入的是一个错误的元素");this._pNode = _obj.parentNode;this._pNode.style.position = "relative";/** * 在这里创建DOM */var _dom,_doc = doc,_el;_dom = _doc.createElement("div"); //日历的盒子元素_dom.className = "date-container";_dom.style.display = "none";/** * 给我们的 input 绑定 focus 事件 */this._obj.onfocus = function(){Array.prototype.forEach.call(doc.querySelectorAll(".date-container"),function(item){item.style.display = 'none';})_dom.style.display = "block";}this._dom = _dom;/** * 调用创建 日历 元素的方法  然后把 节点 append 进入 this._dom 日历的盒子元素 */_dom.appendChild( this.boxTemplate(_doc) );/** * 成功之后 把盒子元素 放进 this._pNode  包裹整个日历插件的容器中  也是 input的父元素 */this._pNode.appendChild(_dom);// 以上就是 整个初始化的分解动作 我们只需要把这几步 逐个实现就好了// 同时在调用 : this.boxTemplate(_doc)  时候  中间 也会分解 很多步骤// 这中间包括  事件绑定 属性添加  dom 节点创建 、、、、},MyDate.prototype.boxTemplate = function(_doc){var _box,_span,_div,_ym,_ym_c1,_ym_c2,_days,_hms,_hms_c1,_hms_c2,_hms_c3,_yearNode,_monthNode,_daysNode,_hourNode,_msNode;_div = _doc.createElement("div"),_span = _doc.createElement("span"),(_box = _div.cloneNode()).className = "show-ymd",(_ym = _div.cloneNode()).className = "show-ym",//box-childred//(_days = _div.cloneNode()).className = "show-days",//box-childred(_hms = _div.cloneNode()).className = "show-hms",//box-childred/** * _ym 的子节点 */(_ym_c1 = _span.cloneNode()).className = "ym-box",_ym_c2 = _ym_c1.cloneNode(true),_ym_c1.appendChild( this.singleDom({"name": "div","cl": "select-btn prev-year","_html": "上一年","type": "click","handler": this.selectYmHandler,"attr": [{"key":"data-type","value": "prev"}]}) ),this._yearNode = _yearNode = this.singleDom({"name": "select","cl": "date-year","type": "change","handler": this.selectChangeHandler,"init": true}),_ym_c1.appendChild( _yearNode ),//这类的标签要立即初始化_ym_c1.appendChild( this.singleDom({"name": "div","cl": "select-btn next-year","_html": "下一年","type": "click","handler": this.selectYmHandler,"attr": [{"key":"data-type","value": "next"}]}) ),_ym_c2.appendChild( this.singleDom({"name": "div","cl": "select-btn prev-month","_html": "上一月","type": "click","handler": this.selectYmHandler,"attr": [{"key":"data-type","value": "prev"}]}) ),this._monthNode = _monthNode = this.singleDom({"name": "select","cl": "date-month","type": "change","handler": this.selectChangeHandler,"init": true}),_ym_c2.appendChild( _monthNode ),_ym_c2.appendChild( this.singleDom({"name": "div","cl": "select-btn next-month","_html": "下一月","type": "click","handler": this.selectYmHandler,"attr": [{"key":"data-type","value": "next"}]}) ),_ym.appendChild( _ym_c1 ),_ym.appendChild( _ym_c2 ),/** * _hms 的子节点 */ (_hms_c1 = _span.cloneNode()).className = "ym-box", _hms_c2 = _hms_c1.cloneNode(true), (_hms_c3 = _span.cloneNode()).className = "selected-btn", this._hourNode = _hourNode = this.singleDom({"name": "select","cl": "date-hour","attr": '',"type": "change","handler": this.selectChangeHandler,"init": true}), _hms_c1.appendChild( _hourNode ), this._msNode = _msNode = this.singleDom({"name": "select","cl": "date-ms","attr": '',"type": "change","handler": this.selectChangeHandler,"init": true}),  _hms_c2.appendChild( _msNode ), _hms_c3.appendChild( this.singleDom({"name": "span","cl": "date-btn sure-btn","_html": "确定","handler": this.sureCancelHandler,"type": "click","attr": [{"key": "data-type","value": 'sure'}]}) ), _hms_c3.appendChild( this.singleDom({"name": "span","cl": "date-btn cancel-btn","_html": "取消","handler": this.sureCancelHandler,"type": "click","attr": [{"key": "data-type","value": 'cancel'}]}) ), _hms.appendChild(_hms_c1), _hms.appendChild(_hms_c2), _hms.appendChild(_hms_c3), _box.appendChild(_ym), this._daysNode = _daysNode = this.singleDom({"name": "div","cl": "show-days","init": true}), _box.appendChild( _daysNode ), _box.appendChild(_hms); return _box;},MyDate.prototype.createHourHandler = function(){/** * 判断是否是今天  */var _pNode = this._pNode,_year = parseInt(this._yearNode.value),_month = parseInt(this._monthNode.value),_day = _pNode.querySelector(".day-list.active"),_hNode = this._hourNode,_hour;if(!_day) {alert("请选择日期");return false;} _day = parseInt(_day.innerHTML);if(_year === this._cyear && _month === this._cmonth && _day === this._cday){_hour = ( new Date() ).getHours();}else{_hour = 23;}_hNode.innerHTML = '';for(let i=0;i<=_hour;i++){_hNode.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? "0" + i : i) + "时"}) );}this.createMsHandler();},MyDate.prototype.clickDaysHandler = function(_this,el){var _className = el.className,_active;if(_className.indexOf(" active") != -1) return false;_active = el.parentNode.querySelector(".active");!_active ? '' : _active.className = _className;el.className = _className + " active";/** * 此时根据 选着的天 来加载小时  只要不是当天  都是24小时 */_this.createHourHandler();},MyDate.prototype.daysTemplate = function (days) {if(!days) throw new Error("days is not a number");var day_box = this._daysNode;day_box.innerHTML = '';for(let i=1;i<=days;i++){day_box.appendChild( this.singleDom({"name": "span","cl": i == days ? "day-list active" : "day-list","type": "click","handler": this.clickDaysHandler,"_html": i < 10 ? "0" + i : i}) );}this.createHourHandler();},MyDate.prototype.createDaysHandler = function(){var _pNode = this._pNode,_year = parseInt(this._yearNode.value),_month = parseInt(this._monthNode.value),_day;/** * 判断是否是今年   * * 是: 判断是否是当月--》是:判断今天是哪一天  不是: 判断这个月的最后一天 * * 不是: 判断选中的这个月的最后一天 *///判断是否是本年if(_year === this._cyear && _month === this._cmonth){//判断是否是当月当年_day = ( new Date() ).getDate();}else{//判断是不是二月if(_month === 2){//判断是不是闰年_day = this.isLeapYear(_year) ? 29 : 28;}else{_day =  ("-1-3-5-7-8-10-12").indexOf("-"+_month) != -1 ?  31 : 30;}}// alert(_day);this.daysTemplate(_day);},MyDate.prototype.createMsHandler = function(){/** * 判断是否是今天  */var _pNode = this._pNode,_year = parseInt(this._yearNode.value),_month = parseInt(this._monthNode.value),_day = _pNode.querySelector(".day-list.active"),_hour = parseInt(this._hourNode.value),_ms,_msNode = this._msNode;if(!_day) {alert("请选择日期");return false;} _day = parseInt(_day.innerHTML);if( _year === this._cyear && _month === this._cmonth && _day === this._cday && _hour === (new Date).getHours() ){_ms = (new Date).getMinutes();}else{_ms = 59;}_msNode.innerHTML = '';for(let i=0;i <= _ms;i++){_msNode.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? "0"+i : i) + ":00"}) )}this.saveSelectTimer({"year": _year,"month": _month < 10 ? "0"+_month : _month,"day": _day < 10 ? "0"+_day : _day,"hour": _hour < 10 ? "0"+_hour : _hour,"ms": "00:00"});},MyDate.prototype.saveSelectTimer = function(option){if(!option) throw new Error("option is not exist");setTimeout(()=>{this._selectTimer = {"year": option["year"] || parseInt( this._yearNode.value ),"month": option["month"] || parseInt( this._monthNode.value ),"day": option["day"] || parseInt( this._daysNode.querySelector(".active").innerHTML ),"hour": option["hour"] || parseInt( this._hourNode.value ),"ms": option["ms"] || parseInt( this._msNode.value ),}}, 25)},MyDate.prototype.selectChangeHandler = function(_this,el){var _className = el.className;switch (_className) {case "date-year"://选择的年份  如果不是当年  月份应该是整个12个月_this.createSelectDom(_this._monthNode,'',"month",parseInt(el.value));_this.createDaysHandler();break;case "date-month":/** * 当月份改变的时候  要重新计算天数 */_this.createDaysHandler();break;case "date-hour":/** * 当月份改变的时候  要重新计算天数 */_this.createMsHandler();break;case "date-ms":/** * 当分钟改变的时候  重新储存 数据 this._selectTimer */_this.saveSelectTimer({"ms": el.value});break;default:// statements_defbreak;}},MyDate.prototype.selectYmHandler = function(_this,el){var _type = el.getAttribute("data-type"),_select = el.parentNode.querySelector("select"),_ops = _select.querySelectorAll("option"),_select_v = parseInt(_select.value),_ops_v = {},_ops_arr = [],_cvalue;if(!_ops) return false;Array.prototype.forEach.call(_ops,function(item){_ops_v[parseInt(item.innerHTML)] = item;_ops_arr.push( parseInt(item.innerHTML) );})/** * 在这里判断 是prev || next */_cvalue = _type == "prev" ? Math.max.apply(null,_ops_arr) : Math.min.apply(null,_ops_arr);if(_select_v === _cvalue)  return false;_select_v = _type == "prev" ? ++_select_v : --_select_v;_ops_v[_select_v].selected = true;_this.selectChangeHandler(_this,_select);},MyDate.prototype.singleDom = function(options){/** * name 必填  否则报错 */var el,attr = options["attr"],type = options["type"],init = options["init"];if(!options || !options["name"]) throw new Error("options is error");el = doc.createElement(options["name"]);el.className = options["cl"] || '';el.innerHTML = options["_html"] || '';if(attr){attr.forEach(function(item,index){el.setAttribute(item["key"], item["value"]);})}if(init){this.selectInitHandler(el);}if(type){this.addEvent(el,type,options["handler"],false);}return el;},MyDate.prototype.selectInitHandler = function(el){var _className = el.className,_date = new Date(),_elc,_type;switch (_className) {case "date-year":_elc = _date.getFullYear();_type = "year";break;case "date-month":_elc = _date.getMonth() + 1;_elc = _elc > 9 ? _elc : "0" + _elc ;_type = "month";break;case "show-days":_elc = _date.getDate();_type = "days";break;case "date-hour":_elc = _date.getHours();_type = "hour";break;case "date-ms":_elc = _date.getMinutes();_type = "ms";break;default:// statements_defbreak;}/** * 调用  创建 select的子节点 */this.createSelectDom(el,_elc,_type);},MyDate.prototype.createSelectDom = function(el,_d,_type,cyear){if(!_type) throw new Error("createSelectDom options error");switch (_type) {case "year":this._cyear = _d;for(let i=_d;i>_d - 20;i--){el.appendChild( this.singleDom({"name": "option","_html": i + "年"}) );}break;case "month":if(!_d){if(cyear && cyear == this._cyear){/** * 选择当前年的时候 */el.innerHTML = '';_d = this._cmonth;for(let i=_d;i >=1 ;i--){el.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? '0'+ i : i) + "月"}) );}}else{if(el.querySelectorAll("option").length === 12) return false;el.innerHTML = '';for(let i=1;i <=12 ;i++){el.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? '0'+ i : i) + "月"}) );}}}else{/** * 初始化的时候 */_d = parseInt(_d);this._cmonth = _d;for(let i=_d;i >=1 ;i--){el.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? '0'+ i : i) + "月"}) );}}break;case "days":this._cday = _d;for(let i=0;i <= _d ;i++){el.appendChild( this.singleDom({"name": "span","cl": i !== _d ? "day-list" : "day-list active","type": "click","handler": this.clickDaysHandler,"_html": i < 10 ? "0" + i : i}) );}break;case "hour":for(let i=_d;i >=0 ;i--){el.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? '0'+ i : i) + "时"}) );}break;case "ms":for(let i=_d;i >=0 ;i--){el.appendChild( this.singleDom({"name": "option","_html": (i < 10 ? '0'+ i : i) + ":00"}) );}this.saveSelectTimer({"ms": (_d < 10 ? '0'+ _d : _d) + ":00"});break;default:// statements_defbreak;}},MyDate.prototype.sureCancelHandler = function(_this,el){var _type = el.getAttribute("data-type");if(_type == 'sure'){var _t = _this._selectTimer,_r = _this._type,_result = _t["year"] + _r + (parseInt(_t["month"]) < 10 ? "0"+parseInt(_t["month"]) : parseInt(_t["month"]) ) + _r + (parseInt(_t["day"]) < 10 ? "0"+parseInt(_t["day"]) : parseInt(_t["day"]) );_this._obj.value = _this._complete ? _result + ' '+(parseInt(_t["hour"]) < 10 ? "0"+parseInt(_t["hour"]) : parseInt(_t["hour"]) ) + ":"+_t["ms"] : _result;}_this._dom.style.display = "none";},MyDate.prototype.addEvent = function(el, eType, handle, bol){// console.log(el.toString() + eType);if(el.addEventListener){           //如果支持addEventListener        el.addEventListener(eType, handle.bind(null,this,el), bol);    }else if(el.attachEvent){          //如果支持attachEvent        el.attachEvent("on"+eType, handle.bind(null,this,el));    }else{                                  //否则使用兼容的onclick绑定        el["on"+eType] = handle.bind(null,this,el);    }},MyDate.prototype.isLeapYear = function(year){return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);},MyDate;})(),win.MyDate = MyDate;})(window,document)

顺便 附上 html 和 css  大家可以复制看下效果:


html:

<div class="box"><div class="date-box"><input type="text" name="" class="date-input" /></div><div class="date-box"><input type="text" name="" class="date-input" /></div></div>

css:

*{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}body,html{width:100%;overflow-x:hidden;color:#4d4d4d;font:14px/1.5 "Helvetica Neue",Helvetica,Arial,"Microsoft Yahei","Hiragino Sans GB","Heiti SC","WenQuanYi Micro Hei",sans-serif}body{-webkit-tap-highlight-color:rgba(255,0,0,0.5);-webkit-font-smoothing:antialiased;background-color:#fff}a{text-decoration:none}img{display:block;width:100%;vertical-align:middle}ul,li{list-style:none}.box{width:800px;height:500px;margin:10px auto;border:1px solid #ccc;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:4px}.date-box{width:60%;height:42px;margin:20px auto;position:relative}.date-box .date-input{width:100%;height:100%;border:none;outline:none;border:1px solid #ccc;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding-left:15px}.date-box .date-input:hover{border-color:#aaaaaa}.date-box .date-input:focus{border-color:#666666}select{border:none;outline:none}.date-container{position:absolute;top:100%;left:50%;transform:translate3d(-50%, 0px, 0px);padding:2px 5px;box-shadow:0px 0px 5px #999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#f8f8f8;overflow:hidden;cursor:pointer;font-size:14px;z-index:9999}.show-ymd,.show-ym,.show-hms,.show-days{width:100%;overflow:hidden}.show-ymd{width:348px}.ym-box{float:left;height:24px;margin-right:10px;position:relative;border:1px solid #cccccc;margin-bottom:4px}.select-btn,.date-year,.date-month{float:left;height:100%}.date-year,.date-month{width:66px;color:#4d4d4d}.select-btn{padding:1px 3px;background-color:#f1f1f1;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.select-btn:hover{background-color:#F3BABA}.show-days{padding:2px}.day-list{display:inline-block;background-color:#f1f1f1;width:42px;height:36px;line-height:36px;text-align:center;margin:0px 3px 4px;font-size:14px;color:#4d4d4d;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.day-list:hover{background-color:#ccc;color:#f8f8f8}.day-list.active{background-color:red;color:#f8f8f8}.show-hms{padding-top:5px}.date-hour,.date-ms{color:#4d4d4d;width:70px;max-height:100px}.selected-btn{float:right;padding-right:10px;padding-top:2px}.date-btn{padding:4px 10px;margin-left:10px;background-color:#ccc;color:#fff;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.date-btn:hover{background-color:red}/*# sourceMappingURL=sDate.css.map */

总结: 一个任务的关键点在于思路逻辑和任务的分解,希望能对需要的道友有些帮助,同时也希望多交流。


原创粉丝点击