日曆實現

 

 日曆要實現下面兩種效果,圖一是週數據,左右滑動切換不一樣周的數據。下拉後,切換成月數據即圖二。在月數據視圖下,上滑切換成周數據。javascript

 

 

 

 

/**
 * 日曆插件 依賴zepto.js
 * 使用:
 * Calendar.initialize('.calendar-zone');
            Calendar.fBind("dateChange", function(date) { //日曆上選中的日期
                self.selectedDate = date;
                
            });
 */
define(function(require,exports,module){
    var Swipe = require('./swipe');
    var Calendar = {
        /**
         * 初始化日曆數據
         * @param    {[type]}                 selector 日曆數據填充到哪一個元素
         * @param    {[type]}                 type    week month 生成周日曆 or 月日曆
         */
        _config:{
            MONTH:"month",  //生成一週數據仍是一月數據
            WEEK:"week",
            SlideTime:400   //動畫效果的時間
        },
        initialize: function(selector){
            this.type = this._config.WEEK;
            this.selector = selector;
            var title_calendar = this.fGetCalendarTitle();
            $(selector).html(title_calendar);

            this.initProp();
            this.fRender(this.CurYear,this.CurMonth,this.CurDay);
        },
        initProp: function(){
            var d = new Date();
            this.CurYear = d.getFullYear();
            this.CurMonth = d.getMonth();
            this.CurDay = d.getDate();
            this.MonthData = this.fGetCalendarData_month(this.CurYear,this.CurMonth);
            this.WeekIndex = this.fCalculatePos(this.MonthData,this.CurYear,this.CurMonth,this.CurDay);
            this.MaxWeek = this.MonthData.length / 7;
            this.eventDate = [];   //有事件的日期
            this.callback = {};  // {dateChange:callback}
            var m = this.CurMonth +1;
            this.selectedDate = this.CurYear+"-"+m+"-"+this.CurDay;  //日曆上選中的日期
            this._width = $(".calendar-content-pas").width();   //日曆控件寬度
            this._initTop = -$(".calendar-title-pas").height()*(this.MaxWeek+1);
        },
        fGetCalendarTitle: function(){
            var title = "<ul class='calendar-title-pas calendar-pas'><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul><div class='calendar-content-pas'></div>";
            return title;
        },
        fRender: function(year,month,day){
            var tpl = this.fLoadTemplate(year,month,day);
             $('.calendar-content-pas').html(tpl);
            if(this.type == this._config.WEEK){
                this.weekHeight = $(".calendar-week-pas").height();
            }
            this._fBindEvt();
        },
        /**
         * 日曆模板數據 month 0-11, day 1-31
         */
        fLoadTemplate: function(year,month,day){
            var dataType = this.type, tpl ="";
            var showMonth = this.CurMonth + 1;
            var data = this.MonthData;
            if(dataType == this._config.MONTH){
                tpl = "<div class='calendar-month-div' style=margin-top:"+ this._initTop+"px" +">"+"<p class='calendar-showmonth-pas'>"+this.fTransfNum2Upper(showMonth)+"月</p><ul class='calendar-month-pas calendar-pas'>";
                var lis = this.fGetLiTpl(data,year,month);
                tpl = tpl + lis +"</ul></div>";
            }else if(dataType == this._config.WEEK){
                var left = -(this.WeekIndex-1)*this._width+"px";
                var ul_wid = (this._width / 7) * data.length + 'px';
                tpl = "<ul class='calendar-week-pas calendar-pas' style=width:"+ ul_wid +";margin-left:"+left+ ">";
                tpl = tpl + this.fGetLiTpl(data,year,month)+"</ul>";
            }
            return tpl;
        },
        //填充每一行的數據
        fGetLiTpl: function(data,year,month){
            var li_tpl = '';
            for(var i=0,len=data.length;i<len;i++){
                var rec = data[i];
                var fillYear = rec.year,fillMonth = rec.month, fillDay = rec.day;
                var isToday = this.fIsCurrentDay(fillYear,fillMonth,fillDay);
                var activeDay = isToday ? fillDay: null;
                var m = fillMonth + 1;
                var attr =  fillYear+"-"+m+"-"+ fillDay;
                var classItem = fillMonth == this.CurMonth ? '' :'unvisibleItem';
                classItem += fillDay == activeDay ? " activeDay" : " normalDay";
                fillDay = isToday ? "今" : fillDay;
                var li_wid = $(".calendar-content-pas").width() / 7 +"px";
                li_tpl += "<li class='"+classItem+"'"+ " calendar-date='"+attr+"'"+" style=width:"+li_wid+"><a href='javascript:void(0)'>"+fillDay+"<i></i></a></li>";
            }
            return li_tpl;
        },
        _fBindEvt: function(){
            var self = this;
            $(".calendar-content-pas li ").on("click",function(){
                var clickObj = this;
                self._fSelectDate(clickObj);
            });
            var swipeObj = new Swipe(".calendar-week-pas");
            swipeObj.bind("swipeLeft",function(){
                self.fGoNextWeek();
            });
            swipeObj.bind("swipeRight",function(){
                self.fGoPrevWeek();
            });
            swipeObj.bind("swipeDown",function(){
                 if(self.type==self._config.MONTH){ //已是月數據
                    return;
                }
                console.log("swipeDown...顯示月數據");
                self.fShowMonthData();
                if(typeof self.callback.slideDown == 'function'){
                    self.callback.slideDown();
                }
            });
            var monthSwipe = new Swipe(".calendar-month-pas");
            monthSwipe.bind("swipeUp",function(){               
                if(self.type==self._config.WEEK){ //已是週數據  屢次上滑操做 只更新一次
                    return;
                }
                console.log("swipeUp...顯示週數據");
                self.fShowWeekData();
            });
        },
        //滑動到上一週數據
        fGoPrevWeek: function(){
            if(this.WeekIndex <= 1){ return; }
            this.WeekIndex--;
            var li_wid = this._width / 7;
            var left = -(this.WeekIndex-1)*(li_wid*7);
            this.fSlideEffect(".calendar-week-pas","margin-left");
            $(".calendar-week-pas").css("margin-left",left+"px");
        },
        fGoNextWeek: function(){
            if(this.WeekIndex >= this.MaxWeek){ return; }
            this.WeekIndex++;
            var li_wid = this._width / 7;
            var left = -(this.WeekIndex-1)*(li_wid*7);
            this.fSlideEffect(".calendar-week-pas","margin-left");
            $(".calendar-week-pas").css("margin-left",left+"px");
        },
        //下拉 顯示月曆
        fShowMonthData: function(){
            this.type = this._config.MONTH;
            this.fUpdateCalendar(this.CurYear,this.CurMonth,this.CurDay);
            var top = -$(".calendar-month-div").height()+"px";
            $(".calendar-month-div").css("margin-top",top);
            this.fSlideEffect(".calendar-month-div","margin-top");
            $(".calendar-month-div").css("margin-top","0");
        },
        //周 日曆
        fShowWeekData: function(){
            this.type = this._config.WEEK;
            var arr = this.selectedDate.split("-");
            var year = parseInt(arr[0]), month = parseInt(arr[1])-1,day = parseInt(arr[2]);
            this.WeekIndex = this.fCalculatePos(this.MonthData,year,month,day);
            var self = this;
           var top = -($(".calendar-month-div").height()-this.weekHeight)+"px";
           $(".calendar-month-div").css("margin-top",top);
            var time = this._config.SlideTime;
            setTimeout(function(){
                 $(".calendar-month-div").remove();
                 console.log('slide end.');
                 console.log('當前類型',self.type);
                 if(self.type==self._config.WEEK){
                     self.fUpdateCalendar(year,month,day);
                 }              
            },time);
        },
        //更新日曆
        fUpdateCalendar: function(year,month,day){
            console.log('更新日曆,日曆類型',this.type);
            this.fRender(year,month,day);
            this.fRenderEventDate();
            this.fRenderSelected(this.selectedDate);
        },
        //在某個元素上使用滑動效果
        fSlideEffect: function(element,attr){
            var time = this._config.SlideTime;
            var style = {
                    '-webkit-transition':attr +" "+time+'ms',
                    'transition':attr + " "+time+'ms',
                    '-webkit-backface-visibility': 'hidden'
                };
            $(element).css(style);
        },
        //綁定自定義事件  對外暴露
        fBind: function(evtName,callback){
            if(evtName=='dateChange'){
                this.callback.dateChange = callback;
            }else if(evtName=='slideDown'){
                this.callback.slideDown = callback;
            }
        },
        //計算周 的位置
        fCalculatePos: function(data,year,month,day){
            var weekIndex = 1;
            for(var i=0,len=data.length;i<len;i++){
                var rec = data[i];
                var fillYear = rec.year,fillMonth = rec.month, fillDay = rec.day;
                if(fillYear==year && fillMonth==month && fillDay==day){
                    weekIndex = Math.ceil( (i+1) / 7);
                }
            }
            return weekIndex;
        },
        //選擇時間
        _fSelectDate: function(clickObj){
            if($(clickObj).hasClass('unvisibleItem')){ return;}
            var date = $(clickObj).attr('calendar-date');
            if(this.selectedDate != date){
                this.selectedDate = date;
                this.fRenderSelected(date);
                if(typeof this.callback.dateChange =='function'){
                    this.callback.dateChange(date);
                }
            }
        },
        //渲染選中日期
        fRenderSelected: function(selectedDate){
            var self = this;
            $(".calendar-content-pas li").each(function(){
                var date = $(this).attr("calendar-date");
                var showday = date.split("-")[2];
                if($(this).hasClass('activeDay') && selectedDate != date){
                    $(this).removeClass('activeDay');
                    $(this).children('a').eq(0).html(showday+"<i></i>");
                }
                if(selectedDate == date){
                    $(this).addClass('activeDay');
                    var arr = date.split("-"),year = arr[0], month = arr[1]-1,day = arr[2];
                    var isCurrentDay = self.fIsCurrentDay(year,month,day);
                    if(isCurrentDay){
                        $(this).children('a').eq(0).html("今<i></i>");
                    }
                }
            });
        },
        //獲取日曆模板  一個月的數據信息
        fGetCalendarData_month: function(year,month){
            var monthInfo = this.fGetMonthInfo(year,month);
            var firstDay = monthInfo.firstDay;
            var lastDay = monthInfo.lastDay;
            var totalDays = monthInfo.totalDays;
            var fillData = []; //{year:,month:0-11,day:1-31}
            var prevData = firstDay!==0 ? this._fGetPrevData(firstDay,year,month) : [];
            fillData = fillData.concat(prevData);
            for(var k=1;k<totalDays+1;k++){
                fillData.push({year:year,month:month,day:k});
            }
            var nextData = lastDay!==6 ? this._fGetNextData(lastDay,year,month) : [];
            fillData = fillData.concat(nextData);
            return fillData;
        },
        // 月日曆模板 不足的用上一個月的補充
        _fGetPrevData: function(firstDay,year,month){
            var prevData = [];
            var lastMonth_info = this.fGetDaysOfPrevMonth(year,month);
            var totalDays_last = lastMonth_info.totalDays;
            for(var i=firstDay-1;i>=0;i--){
                var _prevDay = totalDays_last - i;
                var obj = {year:lastMonth_info.year,month:lastMonth_info.month,day:_prevDay};
                prevData.push(obj);
            }
            return prevData;
        },
        _fGetNextData: function(lastDay,year,month){
            var nextData = [];
            var nextMonth_info = this.fGetDaysOfNextMonth(year,month);
            for(var j=1;j<7-lastDay;j++){  //最後一天 以後的 沒有數據的
                var obj = {year:nextMonth_info.year,month:nextMonth_info.month,day:j};
                nextData.push(obj);
            }
            return nextData;
        },
        //有事件的日期下方加點號 dateArr['20161125','',....]
        fAddEvtCircle: function(dateArr){
            this.eventDate = dateArr;
            this.fRenderEventDate();
        },
        //有事件的日期 加小圓點
        fRenderEventDate: function(){
            var dateArr = this.eventDate;
            $(".calendar-content-pas li").each(function(){
                var date = $(this).attr("calendar-date");
                if($.inArray(date, dateArr)!=-1){
                    $(this).addClass('symbol');
                }
            });
        },
        /**
         * 獲取某一個月的天數、第一天 最後一天周幾   new Date(xxxx,xx,0) 0 即返回上一個月的最後一天
         * @param    {Number}                 year
         * @param    {Number}                 month  月份數 0-11
         */
        fGetDaysOfMonth: function(year,month){
            if(month >11 || month < 0){ return;}
            var d = new Date(year,month+1,0);  //上一個月的最後一天
            var days = d.getDate();  //天數
            return days;
        },
        //獲取上一個月的天數
        fGetDaysOfPrevMonth: function(year,month){
            if(month===0){
                year = year -1;  //獲取上一年的最後一個月
                month = 11;
            }else{
                month = month - 1;
            }
            var days = this.fGetDaysOfMonth(year,month);
            return {totalDays:days,year:year,month:month};
        },
        // 獲取下一個月的天數
        fGetDaysOfNextMonth: function(year,month){
            if(month===11){
                year = year + 1;
                month = 0;
            }else{
                month = month + 1;
            }
            var days = this.fGetDaysOfMonth(year,month);
             return {totalDays:days,year:year,month:month};
        },
        //獲取月份的信息 總天數,第一天 最後一天周幾
        fGetMonthInfo: function(year,month){
            if(month >11 || month < 0){ return;}
            var d = new Date(year,month+1,0);  //上一個月的最後一天
            var days = d.getDate();  //天數
            var lastDay = d.getDay();
            var firstDay = this.fGetWeekOfDay(year,month,1);  //第一天周幾
            return {firstDay:firstDay,lastDay:lastDay,totalDays:days};
        },
       // 獲取某一天 周幾  month  0-11    day  1-31
        fGetWeekOfDay: function(year,month,day){
            if(day > 31 || day < 1){ return; }
            var d = new Date(year,month,day);
            return d.getDay();  //星期幾
        },
        //判斷是不是當前日期
        fIsCurrentDay: function(year,month,day){
            var d = new Date();
            return d.getFullYear() == year && d.getMonth() == month && day == d.getDate();
        },
       fTransfNum2Upper : function(i){
            i = i.toString();
            var NumberArr = ["","一","二","三","四","五","六","七","八","九","十"];
            var result = i <= 10 ? NumberArr[i] : "十"+NumberArr[i.split("")[1]];
            return result;
        }
    };
    module.exports = Calendar;
});
相關文章
相關標籤/搜索