jQuery实现可以扩展的日历


Posted in jQuery onDecember 01, 2020

新的产品需求需要,要写一个这样的日历插件。

效果图如下:

jQuery实现可以扩展的日历

选择日期后,显示当前可以选择的时间,时间的列表是通过ajax从后台获取的一组数据。
而且这个日期存在的情况,还是动态渲染的一个列表里面,再动态渲染的一个日历。

例如:

jQuery实现可以扩展的日历

此时的步骤图渲染是根据后台给的一个list来渲染的,所以,里面的元素但凡要点击,要交互,就要注意事件冒泡。
bootstrap的日历插件,运用起来也没法满足需求,所以被迫自己写了一个日历

代码如下:

var date = new Date()
   var nowYear = date.getFullYear(); //获取当前年份
   var nowMonth = date.getMonth() + 1; //获取当前月份
   var nowDay = date.getDate(); //获取当前天
   var splitString = "-"; //年月日之间的分隔符
   var weekDays = new Array("日", "一", "二", "三", "四", "五", "六"); //星期数组
   var months = new Array("一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"); //月份数组
   var lastDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); //每个月的最后一天是几号

   //变量保存,存储当前选择的年月
   var checkYear = nowYear;
   var checkMonth = nowMonth;

   // //将选择的日期添加到输入框
   function setInput(selectDay) {
    $('#txt_calendar').value = checkYear + splitString + checkMonth + splitString + selectDay;
    hidDate();
   }

// //显示控件
   function showDate() {
    
    createDate(nowYear, nowMonth);//创建日历
    console.log(nowYear, nowMonth, '创建时间日历')
    //计算显示控件位置
    ///获取当前输入框的位置,在实际操作中需要修改此处ID
    var x = $('#txt_calendar').offset().left
    var y = $('#txt_calendar').offset().top + 22
    console.log(x, y, 'x, y', $('#txt_calendar'))
    $('#testID').css({
     left: '-38px',
     top: '37px'
    })
   }
   // /*
   // * 以下拼接日历框
   // * 并定位日历框
   // * */
   // //创建日历样式 
   function createDate(thisYear, thisMonth) {
    console.log(thisYear, thisMonth, '创建日历------------------')
    var createDoc = '<div style="height: 30px;">';
    //当前年月日,点击此处日历自动跳到当前日期
    createDoc += '<p style="width: 100%;height: 30px;text-align: center;color: #999; display: none;" onclick="getThisDay()">当前日期 ' + nowYear + "年" + nowMonth + "月" + nowDay + "号";
    //关闭日历显示
    createDoc += '<span id="closeDate" onClick="hidDate()" style="float: right;font-size: 25px;margin: -20px 3px 0 0;cursor: pointer;">×</span></p></div>';;
    createDoc += '<div style="margin-bottom: 8px;">';
    // 上月
    createDoc += '<span id="lastMonth" style="margin: 0 20px 0 25px;cursor:pointer;"><</span>';
    //创建年份下拉框[1900-2099]年onchange="changeYearAndMonth()">
    createDoc += '<select id ="selectYear" class="selectStyle"';
    for (var y = 1900; y <= 2099; y++) {
     createDoc += "<option value=" + y + ">" + y + "</option>";
    }
    createDoc += "</select>年";
    //创建月份下拉框onchange="changeYearAndMonth()">
    createDoc += '<select id ="selectMonth" style="overflow: auto;" class="selectStyle"';
    for (var m = 0; m <= 12; m++) {
     createDoc += `<option style='z-index: 9999;' value="${m}">${m}</option>`;
    }
    createDoc += "</select>月";
    //下一月 onClick="nextMonthClick()" 
    createDoc += '<span id="nextMonth"style="float: right;margin-right: 25px;cursor:pointer; padding-left: 10px;">></span></div>';
    //创建星期
    createDoc += '<div class="everyWeekDay">';
    for (var i = 0; i < weekDays.length; i++) {
     if (weekDays[i] == "日" || weekDays[i] == "六") {
      createDoc += `<span class="weekday" style="background-color: #18bc9c;color:#ccc;">${weekDays[i]}</span>`
     } else {
      createDoc += `<span style="background-color: #18bc9c;color:#fff;" class="weekday">${weekDays[i]}</span>`
     }
    }
    createDoc += '</div>';
    //创建每月天数
    createDoc += '<div class="everyDay"><div class="marginTop">'; //日期样式DIV
    var thisWeek = getThisWeekDay(thisYear, thisMonth, 1); //算出当前年月1号是星期几
    /*$(this).css({ 'cursor': 'no-drop' })
     * 如果当前不是星期天,创建空白日期占位
     * 若是星期天,则循环输出当月天数
     * 待修改优化,后期改为变色的前一个月日期
     */
    if (thisWeek != 0) {
     for (var i = 0; i < thisWeek; i++) {
      createDoc += '<span class="days"></span>';
     }
    }
    //循环输出当月天
    //getThisMonthDay()获取当月天数
    for (var i = 1; i < getThisMonthDay(thisYear, thisMonth) + 1; i++) {
     // if (thisYear == nowYear && thisMonth == nowMonth && i == nowDay) {
     //  //今天的显示
     //  if (getThisWeekDay(thisYear, thisMonth, i) == 6 || getThisWeekDay(thisYear, thisMonth, i) == 0) {
     //   //今天是周末
     //   createDoc += '<span class="days anyDay" data- style="background-color:#4eccc4;color:#FFFFFF;cursor:pointer;">' + i + '</span>';
     //  } else {
     //   createDoc += '<span class="days anyDay" style="background-color:#4eccc4;color:#FFFFFF;cursor:pointer;">' + i + '</span>';
     //  }
     // } else {
      // 不可选择的变成灰色, 目前是周末变成灰色
      // if (getThisWeekDay(thisYear, thisMonth, i) == 6 || getThisWeekDay(thisYear, thisMonth, i) == 0) {
      //  // onClick="setInput(' + i + ')"
      //  createDoc += '<span id="weekends" class="days anyDay"" style="color:#ccc; cursor:pointer;">' + i + '</span>';
      // } else {
       // console.log(nowDay, 'nowDay-------------')
       if (i == nowDay) {
        createDoc += `<div class="days anyDay" data-date="${thisYear}-${thisMonth}-${i}" style="cursor:pointer;background-color:#4eccc4;color:#FFFFFF;">${i}<div class="timeList">`;
       } else {
        createDoc += `<div class="days anyDay" data-date="${thisYear}-${thisMonth}-${i}" style="cursor:pointer;">${i}<div class="timeList">`;
       }
     
       let weeknum = getThisWeekDay(thisYear, thisMonth, i)
       let weektext = '周' + weekDays[weeknum]
       for (let _i = 0; _i < interviewtimelist.length; _i++) {
        if (weeknum == interviewtimelist[_i].week) {
         createDoc += `<p class='interViewTime' style="width: 100%; border-bottom: 1px solid #ccc;" data-week="${interviewtimelist[_i].week}" data-time="${interviewtimelist[_i].time}" data-amorpm="${interviewtimelist[_i].amorpm}">${weektext} ${interviewtimelist[_i].amorpm} ${interviewtimelist[_i].time}</p>`
          }
       }
       createDoc += '</div></div>'

       
      // }
     // }
     //星期六换行
     if (getThisWeekDay(thisYear, thisMonth, i) == 6) {
      createDoc += "</tr>";
     }
    }
    createDoc += '</div></div>';
    $('#testID').html(createDoc)
    //将创建好的控件字符串添加到div中
    //默认选择当前年份
    console.log(thisMonth, '当前月份为-------------')
    $('#selectYear').val(thisYear)
    //默认选择当前月 
    $('#selectMonth').val(thisMonth)
    if (thisMonth == 1) {
     $('#selectMonth').val('1')
    }
    console.log(thisMonth, '当前月份为-------------', $('#selectMonth').val())
   }//日历创建结束
   // //跳转到当前日 
   function getThisDay() {
    checkYear = nowYear;
    checkMonth = nowMonth;
    createDate(checkYear, checkMonth);
   }

   //上一个月
   $(document).on('click', '#lastMonth', function (event) {
    event.stopPropagation()
    lastMonthClick()
   })
   function lastMonthClick() {
    //若当前是1月份,年份减一,月份变为12
    if (checkMonth == 1) {
     checkYear = checkYear - 1;
     checkMonth = 12;
    } else {
     checkMonth = checkMonth - 1;
    }
    //创建当前月份日期
    createDate(checkYear, checkMonth);
   }

   //下一月
   $(document).on('click', '#nextMonth', function (event) {
    event.stopPropagation()
    nextMonthClick()
   })
   function nextMonthClick() {
    //若当前是12月份,年份加1,月份变为1
    if (checkMonth == 12) {
     checkYear = parseInt(checkYear + 1);
     checkMonth = 1;
    } else {
     checkMonth = parseInt(checkMonth + 1);
    }
    //创建当前月份日期
    createDate(checkYear, checkMonth);
   }

   //年月下拉框-年selectMonth
   $(document).on('click', '.selectStyle', function (event) {
    event.stopPropagation()
   })
   $(document).on('click', '.selectStyle option', function (event) {
    event.stopPropagation()
   })
   // 点击年份
   $(document).on('change', '#selectYear', function (event) {
    event.stopPropagation()
    changeYearAndMonth()
   })
   
   //年月下拉框-月
   $(document).on('change', '#selectMonth', function (event) {
    event.stopPropagation()
    changeYearAndMonth()
   })
   function changeYearAndMonth() {
    checkYear = $('#selectYear').val()
    checkMonth = $('#selectMonth').val();
    
    createDate(checkYear, checkMonth);
   }

   //判断是否为闰年 
   function isLeapYear(year) {
    var isLeap = false;
    if (0 == year % 4 && ((year % 100 != 0) || (year % 400 == 0))) {
     //闰年可以被4整除且不能被100整除,或者能整除400
     isLeap = true;
    }
    return isLeap;
   }

   //获取某月份的总天数
   function getThisMonthDay(year, month) {
    var thisDayCount = lastDays[month - 1]; //获取当前月份的天数
    if ((month == 2) && isLeapYear(year)) {
     //若当前月份为2月,并且是闰年,天数加1
     thisDayCount++;
    }
    return thisDayCount;
   }

   //计算某天是星期几
   function getThisWeekDay(year, month, date) {
    //将年月日创建Date对象,返回当前星期几
    var thisDate = new Date(year, month - 1, date);
    return thisDate.getDay();
   }
   /**
    * 
    * @param {*} curdate 鼠标滑过的日期
    * @param {*} today 今天的日期
    */
   function compareDate(curdate) {
    let today = Date.parse(nowYear + '-' + nowMonth + '-' + nowDay)
    let cur = Date.parse(curdate)
    if (cur <= today) {
     return false
    } else {
     return true
    }
    // var cur = curdate.split('-')
    // var c = Date.parse(curdate)
    
   }
   $(document).on('mouseover', '.anyDay', function (event) {
    event.stopPropagation()
    console.log($(this).context.dataset.date)
    let canclick = compareDate($(this).context.dataset.date) ? true : false
    if ($(this).children().children().length <= 0 || !canclick) { // 不可点击的状态
     $(this).css({ 'cursor': 'no-drop' })
     $(this).siblings().children('.timeList').hide()
     return
    } else { // 可点击的状态
     $(this).children('.timeList').show()
     $(this).siblings().children('.timeList').hide()
    }
   })
   $(document).on('click', '.anyDay', function (event) {
    event.stopPropagation()
    let canclick = compareDate($(this).context.dataset.date) ? true : false
    curInterViewDate = $(this).context.dataset.date
    if ($(this).children().children().length <= 0 || !canclick) { // 不可点击的状态
     $(this).siblings().children('.timeList').hide()
     return
    } else { // 可点击的状态
     $(this).children('.timeList').show()
     $(this).siblings().children('.timeList').hide()
    }
   })
   /**
    * 点击选择当前时间var curClickStatus = ''
   var curInterViewDate = ''
   var curInterViewTime = ''
   var curAmPm = ''
    * 更新页面的显示,以及保存参数后续点击确定的时候,传给后台
    */
   $(document).on('click', '.interViewTime', function (event) {
    event.stopPropagation()
    // curInterViewDate = $(this).context.dataset.
    let week = '周' + weekDays[$(this).context.dataset.week]
    curInterViewTime = $(this).context.dataset.time
    curAmPm = $(this).context.dataset.amorpm
    console.log($(this))
    let text_input = week + ' ' + curInterViewDate + ' ' + curAmPm + ' ' + curInterViewTime
    $('#txt_calendar').val(text_input)
    $('#testID').hide()
   })
   /**
    * 点击面试时间的元素。渲染到页面“请选择面试时间” “”
    * 隐藏日历并恢复日历最初的值。
    * 
    */
   $(document).on('click', '.anyDay', function (event) {
    event.stopPropagation()
    if ($(this).children().children().length <= 0) { // 不可点击的状态
     $(this).css({ 'cursor': 'no-drop' })
     return
    } else { // 可点击的状态
     $(this).children('.timeList').show()
     $(this).siblings().children('.timeList').hide()
    }
    console.log(this, '点击当前元素----', $(this).children().children().length)
   })
   // //关闭日期选择框
   function hidDate() {
    $('#dateOuter').style.display = "none";
   }

目前可以实现需求了,但还有很多的不足,如果有好的建议,欢迎留言哦~

jQuery 相关文章推荐
jQuery.Form实现Ajax上传文件同时设置headers的方法
Jun 26 jQuery
jQuery实现选中行变色效果(实例讲解)
Jul 06 jQuery
基于Jquery Ajax type的4种类型(详解)
Aug 02 jQuery
详解webpack3如何正确引用并使用jQuery库
Aug 26 jQuery
jquery手机触屏滑动拼音字母城市选择器的实例代码
Dec 11 jQuery
基于jquery.page.js实现分页效果
Jan 01 jQuery
jQuery niceScroll滚动条错位问题的解决方法
Feb 03 jQuery
基于jquery实现左右上下移动效果
May 02 jQuery
js与jQuery实现获取table中的数据并拼成json字符串操作示例
Jul 12 jQuery
jquery将信息遍历到界面上实例代码
Jan 21 jQuery
jQuery实现小火箭返回顶部特效
Feb 03 jQuery
jquery+css3实现的经典弹出层效果示例
May 16 jQuery
jQuery实现容器间的元素拖拽功能
Dec 01 #jQuery
jQuery实现查看图片功能
Dec 01 #jQuery
基于jQuery拖拽事件的封装
Nov 29 #jQuery
jQuery实现动态操作table行
Nov 23 #jQuery
jQuery-App输入框实现实时搜索
Nov 19 #jQuery
JQuery+drag.js上传图片并且实现图片拖曳
Nov 18 #jQuery
JavaScript枚举选择jquery插件代码实例
Nov 17 #jQuery
You might like
实现树状结构的两种方法
2006/10/09 PHP
thinkphp实现发送邮件密码找回功能实例
2014/12/01 PHP
深入浅析php json 格式控制
2015/12/24 PHP
PHP在innodb引擎下快速代建全文搜索功能简明教程【基于xunsearch】
2016/10/14 PHP
js 设置选中行的样式的实现代码
2010/05/24 Javascript
js继承的实现代码
2010/08/05 Javascript
使用JavaScript构建JSON格式字符串实现步骤
2013/03/22 Javascript
jquery获取子节点和父节点的示例代码
2013/09/10 Javascript
JavaScript结合AJAX_stream实现流式显示
2015/01/08 Javascript
jquery中cookie用法实例详解(获取,存储,删除等)
2016/01/04 Javascript
ionic js 复选框 与普通的 HTML 复选框到底有没区别
2016/06/06 Javascript
JQuery和HTML5 Canvas实现弹幕效果
2017/01/04 Javascript
JavaScript正则表达式的贪婪匹配和非贪婪匹配
2017/09/05 Javascript
node通过express搭建自己的服务器
2017/09/30 Javascript
原生js封装添加class,删除class的实例
2017/11/06 Javascript
vue组件name的作用小结
2018/05/23 Javascript
详解webpack-dev-server使用方法
2018/09/14 Javascript
Vue用v-for给循环标签自身属性添加属性值的方法
2018/10/18 Javascript
Vue切换Tab动态渲染组件的操作
2020/09/21 Javascript
[45:18]完美世界DOTA2联赛循环赛 PXG vs IO 第二场 11.06
2020/11/09 DOTA
python定时检查启动某个exe程序适合检测exe是否挂了
2013/01/21 Python
Python获取linux主机ip的简单实现方法
2016/04/18 Python
浅谈五大Python Web框架
2017/03/20 Python
python下实现二叉堆以及堆排序的示例
2017/09/29 Python
pytorch训练imagenet分类的方法
2018/07/27 Python
爬虫代理的cookie如何生成运行
2020/09/22 Python
浅谈HTML5 defer和async的区别
2016/06/07 HTML / CSS
英国健身专家:WIT Fitness
2021/02/09 全球购物
2014应届本科生自我评价
2014/09/13 职场文书
2015年119消防宣传日活动总结
2015/03/24 职场文书
行政二审代理词
2015/05/25 职场文书
学校学习型党组织建设心得体会
2019/06/21 职场文书
创业计划书之农家乐
2019/10/09 职场文书
详解Java实践之抽象工厂模式
2021/06/18 Java/Android
Windows Server 2012 R2 磁盘分区教程
2022/04/29 Servers
MySql数据库触发器使用教程
2022/06/01 MySQL