支持全选及全选周末功能的日历插件开发教程

忙里偷闲,终于有点时间写博客了。今天我要说的这款插件,是我自己在项目中开发的。前段时间花了好多心思Google,找了很多的插件,但是没有一款符合项目要求。想想自己虽然不是什么技术大牛,但是写个拙劣的插件应该还是可行的。于是花了一天时间把流程及基础功能做好了,又继续花了一天时间完善了下,现在看来,也没有白费心思。至少这个东西没有走向灭亡,而是继续在项目中实现它的价值。好了,废话不多说,上菜!
日历开源,已经放在github上面了。git@github.com:BGOnline-CN/BGOCalender.git

博客中有什么不对的地方,希望大家能帮我指出来,冰果在这里先谢过了!

1.买房子,一定得隔音!

;(function($) {
  // 这里是我们的插件代码   
})(jQuery);

2.打扫卫生

;(function($) {
  
  $.fn.extend({ // 这里是我们的插件代码   
    'BGOCalender': function(options) { // 开始写插件,BGOCalender就是我们的插件名

    }
  });
})(jQuery);

3.通水电,哥们以前通下水道的,这个难不倒我。嘿嘿嘿~

;(function($) {
  $.fn.extend({ // 这里是我们的插件代码   


    'BGOCalender': function(options) { // 开始写插件,BGOCalender就是我们的插件名

      // 既然是日历插件,那少不了的东西就是 Date() 方法啦
      var date = new Date(); // 实例化 日期函数

      // 1.好了,房子打扫干净了,咋们把水电通通吧。(默认参数配置)
      var defaultOpts = { 
        today: date.getDate(), // 当天
        month: date.getMonth(), // 当月
        year: date.getFullYear(), // 当年
        data: [], // 接收服务器数据
        language: cn, // 语言
        callback: function() {} //回调函数
      } 
      
      // 接收用户自定义参数 options 如果有则覆盖默认参数,否则使用默认参数
      var opts = $.extend(defaultOpts, options || {});
      
      var monthDays = [31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 一年中,每月的天数,这里你可能会发现2月有点奇怪,不是还有闰月吗?好的,不急,咋们后面会处理。
      var cn = {
        weekLang: ['\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u65e5'], // 周一到周日,中文语言包
        //monthLang: ['\u4e00\u6708', '\u4e8c\u6708', '\u4e09\u6708', '\u56db\u6708', '\u4e94\u6708', '\u516d\u6708', '\u4e03\u6708', '\u516b\u6708', '\u4e5d\u6708', '\u5341\u6708', '\u5341\u4e00\u6708', '\u5341\u4e8c\u6708'] // 月份的语言包,我没做,因为项目中并没有用到
      }

      // 好了,接下来,处理我们的平年闰年了
      var isLeapYear = function(y, m) { // 前面的开发规范我有说过,只包含一条语句的代码块,我们可以再一行内显示
        if(m < 0) { m = 11; } // 这里的作用是,JS返回给我们的月份是从0开始的,也就是说,我们想要得到1月,必须得告诉他我们要的是0月,所以我们要做个判断,以便我们切换年份时使用
        if(m > 11) { m = 0; }
        if(m == 1) { // 判断是否为闰年,并返回该月天数
          return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 29 : 28;
        }else { return monthDays[m]; }
      }
      
        // 返回上一个月天数
        var preMonthDays = function(y, m) {
           return isLeapYear(y, m-1);
        }
        

        // 返回该月第一天是星期几
        var firstDayWeek = function(y, m) {
            return new Date(y, m, 1).getDay() == 0 ? 7 : new Date(y, m, 1).getDay();
        }
        
        // 日历表头
        for(var i = 0; i < cn.weekLang.length; i++) {
            $('> .calender > table > thead > tr > th',       this).eq(i).html(opts.language.weekLang[i]);
        }
    }
  });
})(jQuery);

到这里,结合我们的html,一个简单的日历就出来了。

这个日历的html我是直接分开来写的,没有用js生成。为了扩展性和方便项目,你们有需要可以自行修改。

4.实现上一个月与下一个月功能

        // 载入今天和当月,在项目中用不上,所以我注释掉了
        // // 载入今天
        // $('.cur').click(function() {
        //     opts.month = date.getMonth();
        //     opts.year = date.getFullYear();
        //     opts.today = date.getDate();
        //     td.removeClass('selectDate');
        //     initCalender(opts.year, opts.month);
        // });
        
        // // 载入当月
        // $('.cur').click(function() {
        //     opts.month = date.getMonth();
        //     opts.year = date.getFullYear();
        //     initCalender(opts.year, opts.month);
        // });
        
        
        // 载入上一个月
        $('.preClass').click(function() {
            opts.month--;
            if(opts.month < 0) {
                opts.month = 11;
                opts.year--;
            }
            initCalender(opts.year, opts.month);
        });
        
        // 载入下一个月
        $('.nextClass').click(function() {
            opts.month++;
            if(opts.month > 11) {
                opts.month = 0;
                opts.year++;
            }
            initCalender(opts.year, opts.month);
        });

5.载入日历

        cData = [];
        sData = [];
        var showSelectInfo = function(totalData) {
            
            var removeRepeat = function(index,array) { // 根据指定下标删除数组 供过滤时调用
                if(index >= 0 && index < array.length) {
                    for(var i = index; i < array.length; i++) {
                        array[i] = array[i+1];
                    }
                    array.length = array.length - 1;
                }
                return array;
            }
                
            var filterArray = function(arr) { // 过滤数组中重复数据并返回新数组
                for(var i=0; i< arr.length; i++) {
                    for(var j = i + 1; j < arr.length; j++) {
                        if(arr[i] == arr[j]) {
                            arr = removeRepeat(j,arr); 
                            i = -1;
                            break;
                        }
                    }
                }
                return arr;  
            } 
            
            var bubbling = function(arr) { // 排序
                var flag = false;
                var temp;
                for(var i = 0; i < arr.length - 1; i++) {
                    for(var j = 0; j < arr.length-1-i; j++) {
                        if(arr[j] > arr[j+1]) {
                            temp = arr[j];
                            arr[j] = arr[j+1];
                            arr[j+1] = temp;
                            flag = true;
                        }
                    }
                    if(flag) {
                        flag = false;
                    }else {
                        break;
                    }
                }
            }
            
            totalData = filterArray(totalData);
            
            bubbling(totalData);
            
            // 右侧显示数值
            switch(opts.pattern) {
                case 1:
                    $('.startClass > span.dateTitle').html('开班日期');
                    $('.endClass > span.dateTitle').html('结班日期');
                    break;
                case 2:
                    $('.startClass > span.dateTitle').html('上课日期');
                    $('.endClass > span.dateTitle').html('结课日期');
                    break;
            }
            if(totalData.length < 1) {
                $('.startClass > span.dateCon').html(''); // 开课日期
                $('.endClass > span.dateCon').html(''); // 结课日期
            }else {
                $('.startClass > span.dateCon').html(totalData[0]); // 开课日期
                $('.endClass > span.dateCon').html(totalData[totalData.length-1]); // 结课日期
            }
            
            $('.totalClass > p > span').html(totalData.length); // 总上课天数
            
            // 剩余上课天数
            var count = 0;
            var fullToday;
            if(date.getMonth() < 10 && date.getDate() < 10) {
                fullToday = date.getFullYear() + '-' + '0' + (date.getMonth() + 1) + '-' + '0' + date.getDate();
            }else if(date.getMonth() < 10 && date.getDate() > 10) {
                fullToday = date.getFullYear() + '-' + '0' + (date.getMonth() + 1) + '-' + date.getDate();
            }else if(date.getMonth() > 10 && date.getDate() < 10) {
                fullToday = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + '0' + date.getDate();
            }else if(date.getMonth() > 10 && date.getDate() > 10) {
                fullToday = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
            }

            for(var i = 0; i < totalData.length; i++) {
                if(totalData[i] >= fullToday) {
                    count++;
                }
            }
            $('.onlyClass > p > span').html(count);

        }
        
        var addTotalData = function(e, totalData) { // 载入totalData
            if(e.text() < 10) {
                totalData.push($('.year').text()+'-'+$('.month').text()+'-'+'0'+e.text());
            }else {
                totalData.push($('.year').text()+'-'+$('.month').text()+'-'+e.text());
            }
        }
        
        var removeTotalData = function(e, totalData) { // 删除totalData
            if(e.text() < 10) {
                totalData.splice($.inArray($('.year').text()+'-'+$('.month').text()+'-'+'0'+e.text(), totalData),1);
            }else {
                totalData.splice($.inArray($('.year').text()+'-'+$('.month').text()+'-'+e.text(), totalData),1);
            }
        }
        
        var generateCalendar = function(y, m) {
            
            // 当前所在日期
            $('.year').html(y);
            if(m+1 < 10) {
                $('.month').html('0'+parseInt(m+1));
            }else {
                $('.month').html(parseInt(m+1));
            }

            var data = [];
            // 用上月号数补齐当月1号前空余号数
            for(var i = firstDayWeek(y, m) - 2; i >= 0; i--) {
                data.push('<span class="notMonthly">' + (preMonthDays(y, m)-i) + '</span>');
            }
            
            // if($('.month').text() < 10) { // 拼装参数
            //     var holiday = $('.year').text()+'0'+$('.month').text();
            // }else {
            //     var holiday = $('.year').text()+$('.month').text();
            // }
            // $.ajax({ // 获取节假日数据
            //     type: "GET",
            //     url: "http://apis.baidu.com/xiaogg/holiday/holiday",
            //     data: {d: holiday, apikey: '22ccbd220dba0561bbe2177d84d501cf'},
            //     headers : {'apikey':''},
            //     dataType: "json",
            //     success: function(response) {
            //         var res = response[holiday];
            //         for(var k = 0; k <= res.length; k++) {
            //             for(var i = 1; i <= 31; i++) {
            //                 if(i == res[k].slice(2)) {
            //                     // if(td.eq(i).text() == i) {
            //                     //     //td.eq(i).addClass('holiday')
            //                     //     alert(td.eq(i).text())
            //                     // }
            //                 }
            //             }
            //         }
            //     }
            // });


            // 获得当月号数
            for(var i = 1; i <= isLeapYear(y, m); i++) {
                data.push(i);
            }
            

            // 用下月号数补齐当月最后空余号数
            var lackNum = td.length - data.length;
            for(var i = 1; i <= lackNum; i++) {
                data.push('<span class="notMonthly">' + i + '</span>');
            }
            
            
            // 载入日历
            for(var i = 0; i < data.length; i++) {
                td.eq(i).html(data[i]);
                if(data[i] < 10) {
                    td.eq(i).attr({name:$('.year').text() + '-' + $('.month').text() + '-' + '0' + data[i]});
                }else {
                    td.eq(i).attr({name:$('.year').text() + '-' + $('.month').text() + '-' + data[i]});
                }
                
                for(var k = 0; k < cData.length; k++) {
                    if(td.eq(i).attr('name') == cData[k]) {
                        td.eq(i).addClass('selectDate');
                    }
                }
                for(var j = 0; j < sData.length; j++) {
                    if(td.eq(i).attr('name') == sData[j]) {
                        td.eq(i).addClass('selectStuDate');
                    }
                }
            }
            
            // 周末特别标识
            for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
                if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
                    td.eq(i).addClass('holiday');
                }
            }
            
        }

6.日历初始化

         switch(opts.pattern) {
            
            case 1: // 开课日历
            
                // 初始化日历
                var initCalender = function(y, m) {
                    
                    showSelectInfo(cData);

                    // 复位checkbox
                    $('.selectWeekend').removeAttr('checked');
                    $('.selectAll').removeAttr('checked');

                    td.removeClass('selectDate');
                    
                    generateCalendar(y, m);
                    
                }

                cData = [];
                // 用户参数 data 与 历史cData 并集
                var mergeArray = function(arr1, arr2) { 
                    for (var i = 0, j = 0, ci, r = {}, c = []; ci = arr1[i++] || arr2[j++]; ) {
                        if (r[ci]) continue;
                        r[ci] = 1;
                        c.push(ci);
                    }
                    return c;
                }
                cData = mergeArray(opts.classData, cData);

                // 全选周末
                $('.selectWeekend').click(function() {
                    var y = opts.year;
                    var m = opts.month;
                    if($(this).is(':checked')) {
                        for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
                            if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
                                td.eq(i).addClass('selectDate');                     
                                addTotalData(td.eq(i), cData);
                            }
                        }
                    }else {
                        for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
                            if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
                                td.eq(i).removeClass('selectDate');
                                removeTotalData(td.eq(i), cData);
                            }
                        }
                    }
                    
                });
                
                // 全选当月
                $('.selectAll').click(function() {
                    if($(this).is(':checked')) {
                        td.removeClass('selectDate');
                        for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
                            td.eq(i).addClass('selectDate');
                            addTotalData(td.eq(i), cData);
                        }
                        $('.selectWeekend').prop("checked",'true');
                    }else {
                        for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
                            td.eq(i).removeClass('selectDate');
                            removeTotalData(td.eq(i), cData);
                        }
                        $('.selectWeekend').removeAttr("checked");
                    }
                });
                
                
                // 点选号数
                td.click(function() {
                    if($(this).children().hasClass('notMonthly')) {
                        
                        // 这里处理如果点击了上一个月的号数的逻辑

                    }else {
                        if($(this).hasClass('selectDate')) {
                            removeTotalData($(this), cData);
                            $(this).removeClass('selectDate');
                        }else {
                            $(this).addClass('selectDate'); 
                            addTotalData($(this), cData);
                        }
                    }
                })
                break;
                
            case 2: // 学生日历
            
                // 初始化日历
                var initCalender = function(y, m) {
                    
                    showSelectInfo(sData);

                    // 复位checkbox
                    $('.selectWeekend').removeAttr('checked');
                    $('.selectAll').removeAttr('checked');

                    td.removeClass('selectDate');
                    td.removeClass('selectStuDate');
                    
                    generateCalendar(y, m);

                }

                // 用户参数 stuData 与 历史sData 并集
                var mergeArray = function(arr1, arr2) { 
                    for (var i = 0, j = 0, ci, r = {}, c = []; ci = arr1[i++] || arr2[j++]; ) {
                        if (r[ci]) continue;
                        r[ci] = 1;
                        c.push(ci);
                    }
                    return c;
                }
                cData = opts.classData;
                sData = mergeArray(opts.stuData, sData);

                // 全选周末
                $('.selectWeekend').click(function() {
                    var y = opts.year;
                    var m = opts.month;
                    if($(this).is(':checked')) {
                        for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
                            if((new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) && td.eq(i).hasClass('selectDate')) {
                                td.eq(i).addClass('selectStuDate');  
                                addTotalData(td.eq(i), sData);
                            }
                        }
                    }else {
                        for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
                            if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
                                if(td.eq(i).hasClass('selectDate')) {
                                    td.eq(i).removeClass('selectStuDate');                
                                    removeTotalData(td.eq(i), sData);
                                }
                            }
                        }
                    }
                    
                });
                
                // 全选当月
                $('.selectAll').click(function() {
                    if($(this).is(':checked')) {
                        td.removeClass('selectStuDate');
                        for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
                            if(td.eq(i).hasClass('selectDate')) {
                                td.eq(i).addClass('selectStuDate');                
                                addTotalData(td.eq(i), sData);
                            }
                        }
                        $('.selectWeekend').prop("checked",'true');
                    }else {
                        for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
                            if(td.eq(i).hasClass('selectDate')) {
                                td.eq(i).removeClass('selectStuDate');                
                                removeTotalData(td.eq(i), sData);
                            }
                        }
                        $('.selectWeekend').removeAttr("checked");
                    }
                });
                
                // 点选号数
                td.click(function() {
                    if($(this).children().hasClass('notMonthly')) {
                        
                        // 这里处理如果点击了上一个月的号数的逻辑

                    }else {
                        if($(this).hasClass('selectDate')) {
                            if($(this).hasClass('selectStuDate')) {
                                removeTotalData($(this), sData);
                                $(this).removeClass('selectStuDate');
                            }
                            else {
                                $(this).addClass('selectStuDate'); 
                                addTotalData($(this), sData);
                            }
                        }
                    }
                })
                break;
        }
         
        
        
        
        // 执行初始化
        initCalender(opts.year, opts.month);

7.回调函数

        // 回调函数
        opts.callback(function() { 

            switch(opts.pattern) {
                case 1: 
                    showSelectInfo(cData); // 处理cData及展示数据
                    if(cData.length > 0) { // 返回数据
                        return cData;
                    }
                    break;
                case 2: 
                    showSelectInfo(sData);
                    if(sData.length > 0) { // 返回数据
                        return sData;
                    }
                    break;
            }
            
        });

8.调用日历

        <script>
        
        /**
         * 参数列表:
         *      year: 年份 int/string
         *      month: 月份 int/string 默认从0开始 如传入1将获得 2月数据
         *      today: 号数 int/string
         *      classData: 用于接收服务器传过来的班级课表数据 并在日历上标注 array
         *      stuData: 用于接收服务器传过来的学生课表数据 并在日历上标注 array
         *      language: 语言 默认中文
         *      patternNum: 切换日历模式 默认1班级课表 可以接收参数1,2
         *      callback: 回调函数 返回日历选中的值 返回值类型array    
         */
        

        if(parseInt(sessionStorage.editOrAdd)) {
            var classData = window.parent.class_tableData; // 获取服务器数据
            var stuData = window.parent.stuData;
        }

        var patternNum = window.parent.patternNum;
        
        $('.BGOC').BGOCalender({
            
            pattern: patternNum,
            classData: classData,
            stuData: stuData,
            
            callback: function(data) {
                calenderData = data();
                $('.calenderTable > tbody > tr > td, .selectAll, .selectWeekend').click(function() {
                    calenderData = data();
                    console.log(calenderData);
                });
            }
        });    
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容