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模拟实现天猫购物车动画效果实例代码
May 25 jQuery
基于jquery实现多选下拉列表
Aug 02 jQuery
jQuery选择器特殊字符与属性空格问题
Aug 14 jQuery
jQuery事件对象的属性和方法详解
Sep 09 jQuery
jQuery实现的页面遮罩层功能示例【测试可用】
Oct 14 jQuery
jQuery实现简单的下拉菜单导航功能示例
Dec 07 jQuery
jQuery实现图片上传预览效果功能完整实例【测试可用】
May 28 jQuery
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 jQuery
使用jquery的cookie实现登录页记住用户名和密码的方法
Mar 13 jQuery
jQuery事件绑定和解绑、事件冒泡与阻止事件冒泡及弹出应用示例
May 13 jQuery
jQuery 隐藏/显示效果函数用法实例分析
May 20 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
基于qmail的完整WEBMAIL解决方案安装详解
2006/10/09 PHP
php微信公众平台开发之微信群发信息
2016/09/13 PHP
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
2009/02/14 Javascript
关于JavaScript中var声明变量作用域的推断
2010/12/16 Javascript
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
用svg制作富有动态的tooltip
2015/07/17 Javascript
jQuery Validation PlugIn的使用方法详解
2015/12/18 Javascript
浅谈JavaScript 覆盖原型以及更改原型
2016/08/31 Javascript
jquery attr()设置和获取属性值实例教程
2016/09/25 Javascript
vue实现todolist单页面应用
2017/04/11 Javascript
angular-ngSanitize模块-$sanitize服务详解
2017/06/13 Javascript
深入理解vue $refs的基本用法
2017/07/13 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
解决循环中setTimeout执行顺序的问题
2018/06/20 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
解决layUI的页面显示不全的问题
2019/09/20 Javascript
js定时器出现第一次延迟的原因及解决方法
2021/01/04 Javascript
Python中datetime常用时间处理方法
2015/06/15 Python
Python遍历目录并批量更换文件名和目录名的方法
2016/09/19 Python
python爬取各类文档方法归类汇总
2018/03/22 Python
在pycharm 中添加运行参数的操作方法
2019/01/19 Python
Python写出新冠状病毒确诊人数地图的方法
2020/02/12 Python
Django模板报TemplateDoesNotExist异常(亲测可行)
2020/12/18 Python
数控专业毕业生求职信范文
2013/09/21 职场文书
应届大学生求职的自我评价
2013/11/17 职场文书
汽车销售顾问求职自荐信
2014/01/01 职场文书
党员公开承诺书
2014/03/25 职场文书
个人承诺书怎么写
2014/05/24 职场文书
计生工作先进事迹
2014/08/15 职场文书
2014年党员学习“三严三实”思想汇报
2014/09/15 职场文书
补充协议书
2015/01/28 职场文书
2015羊年春节慰问信
2015/02/14 职场文书
单身申明具结书
2015/02/26 职场文书
2015年六一儿童节演讲稿
2015/03/19 职场文书
大学生干部培训心得体会
2016/01/06 职场文书
十大最强飞行系宝可梦,BUG燕上榜,第二是飞行系王者
2022/03/18 日漫