JS時間軸效果(類似於qq空間時間軸效果)

weixin_34321753發表於2013-11-04

       在上一家公司寫了一個時間軸效果,今天整理了下,感覺有必要寫一篇部落格出來 給大家分享分享 當然程式碼還有很多不足的地方,希望大家多指點指點下,此效果類似於QQ空間或者人人網空間時間軸效果,當時也是為了需求 研究了下qq空間邏輯(當然JS程式碼壓縮了肯定看不到的),只是當時研究了下他們HTML結構和css結構,所以仿照他們那種邏輯自己也寫了一個出來。先來看看是個什麼樣的吧!如下圖所示:

需求分析:左側是一個時間列表 右側是一個時間控制抽,當時的需求是這樣的:預設頁面一開啟 只載入當前年份所有列表載入出來 當前年份的控制軸展開出來,預設的焦點在最近的月份,如上圖在當前的10月份或者下圖的12月份,當滾動條滾動的時候再繼續判斷 如果左側滾動到幾月份的時候 那麼右側控制抽當前的焦點也在幾月份,當滾動到上一個年份的時候 那麼當前的年份控制軸收縮起來 上一個年份控制軸展開出來,如下圖所示:

 

當我們點選某一年份的時候 滾動到當前的年份,當我點選某一年中某一月份的時候 滾動到當前年份中對應的月份上來。

當然下面的程式碼我是用到的是淘寶的KISSY框架  當然如果改成Jquery框架也是一樣的,沒有很大的差別 只是用了一下"延遲載入"和一些選擇器而已,首先我們如果要做成這樣的話 要知道有2個請求 一個是左側列表請求返回的資料 一個是右側的年份和月份返回的資料 下面我們可以先來看看 開發給我當時返回的資料格式是個什麼樣的,

左側列表的JSON資料如下圖:

預設情況下是最近年份 當我滾動到2012年時候 再繼續發個2012年的請求 把2012年的相對應的資料渲染出來,同理2011年也一樣.

再來看看年份和月份的JSON資料吧 如下圖:

下面我一步步來分析下 我當時的做法:

1. 首先我需要HTML結構 如下圖所示:

<div class="tao-allMonth-w990"> 
        <div class="tao-video-left J_Video_Left" id="J_Video_Left"></div> 
        <div class="tao-year-right"> 
            <div class="mod-timelinenav"> 
                <ul id="timelinenavpanel" class="timelinenav-panel isScroll"></ul> 
            </div> 
        </div> 
    </div>

其中 id="J_Video_Left"id="timelinenavpanel" 在初始化的時候 是可以配置的 也就是說 他們叫什麼名字並不重要,依賴於這個HTML結構。

2. 依賴於css程式碼 如下:

<style>
	 .tao-allMonth-w990 {width: 990px;margin: 100px auto 0;overflow: hidden;	}
	.tao-video-left {float:left;width: 620px;overflow: hidden;}
	.tao-video-block {width: 620px;overflow: hidden;}
	.tao-header-title {width: 100%;height: 26px;overflow: hidden;}
	.tao-header-title {color: #FF6600;font-family: "Microsoft yahei";font-size: 18px;font-weight: 700;padding-left: 42px;}
	.tao-dottle-top {width: 10px;height: 40px;margin-left: 68px;background: none repeat scroll 0 0 #FFCC99;overflow: hidden;	}
	.tao-video-content {position: relative;width: 620px;overflow: hidden;}
	.tao-video-content .addBlock {
		background: none repeat scroll 0 0 #FFCC99;
		height: 16px;
		left: 68px;
		position: absolute;
		width: 10px;
	}
	.left-date {
		color: #FF6600;
		float: left;
		font-family: "Microsoft yahei";
		font-size: 14px;
		height: 20px;
		line-height: 20px;
		margin-top: 18px;
		overflow: hidden;
		width: 60px;
	}
	.left-date span {
		float: left;
	}
	.tao-video-content .tao-line {
		background: url("http://img02.taobaocdn.com/tps/i2/T1je8uXEBgXXagEfc2-10-205.png") no-repeat scroll 0 0 rgba(0, 0, 0, 0);
		display: inline;
		float: left;
		height: 205px;
		margin: 24px 0 0 8px;
		overflow: hidden;
		width: 10px;
	}
	.tao-inner-content {
		background: url("http://img03.taobaocdn.com/tps/i3/T16VXtXBNiXXXPeW.X-519-190.png") no-repeat scroll 0 0 rgba(0, 0, 0, 0);
		display: inline;
		float: left;
		height: 190px;
		margin: 0 0 0 20px;
		overflow: hidden;
		width: 519px;
	}
	.tao-inner-block {
		height: 130px;
		margin: 30px 0 0 40px;
		overflow: hidden;
		width: 450px;
	}
	.tao-inner-block .inner-left {
		float: left;
		height: 130px;
		overflow: hidden;
		width: 230px;
	}
	.inner-left .alink {
		display: block;
		height: 130px;
		overflow: hidden;
		position: relative;
		width: 230px;
	}
	.inner-left .alink img {
		display: block;
		height: 130px;
		width: 230px;
	}
	.tao-inner-block .icon-player {
		background: url("http://img02.taobaocdn.com/tps/i2/T1J5FFXy8cXXaiphQj-60-145.png") no-repeat scroll 0 -40px rgba(0, 0, 0, 0);
		height: 50px;
		left: 10px;
		overflow: hidden;
		position: absolute;
		top: 68px;
		width: 50px;
		z-index: 10;
	}
	.inner-right {
		float: right;
		height: 130px;
		width: 202px;
	}
	.inner-date {
		color: #666666;
		font-family: "Tahoma";
	}
	.inner-title {
		height: 22px;
		line-height: 22px;
		margin-top: 5px;
		overflow: hidden;
		width: 202px;
	}
	.inner-title a {
		color: #333333;
		font-family: "Microsoft yahei";
		font-size: 18px;
		font-weight: 700;
	}
	.inner-title a:hover {
		color: #FF1155;
		text-decoration: none;
	}
	.inner-content {
		color: #999999;
		line-height: 18px;
		margin-top: 12px;
	}
	.tao-year-right {
		float: right;
		overflow: hidden;
		width: 311px;
	}
	.tao-year-right .mod-fixed {
		overflow: hidden;
		position: fixed;
		top: 0;
		width: 60px;
		z-index: 10;
	}
	.mod-timelinenav {
		margin-top: 20px;
	}
	.mod-timelinenav .yearlink {
		display: inline-block;
	}
	.mod-timelinenav a {
		display: inline-block;
	}
	.mod-timelinenav a:hover {
		text-decoration: none;
	}
	.mod-timelinenav .yearlink, .mod-timelinenav .monthlink {
		border-left: 10px solid #74C2FA;
		color: #7FCCFF;
		font-family: "Tahoma";
		line-height: 20px;
		padding-left: 8px;
	}
	.mod-timelinenav .norecord {
		display: none;
	}
	.mod-timelinenav .active .yearlink, .mod-timelinenav .active .monthlink {
		border-left: 10px solid #0099FF;
		color: #0099FF;
		font-family: "Tahoma";
		line-height: 20px;
		padding-left: 8px;
	}
	.mod-timelinenav .active .monthlink {
		color: #7FCCFF;
	}
	.mod-timelinenav .highlight .monthlink {
		color: #0099FF;
		font-family: "Tahoma";
	}
	.mod-timelinenav .active .timelinenav-mpanel {
		display: block;
	}
	.mod-timelinenav .timelinenav-mpanel {
		display: none;
	}
	.timelinenav-panel {
		overflow: hidden;
		width: 60px;
	}
	.timelinenav-panel li {
		margin: 1px 0;
	}
	.timelinenav-panel li.active, .timelinenav-panel li.active .timelinenav-mpanel li {
		margin: 0;
	}
	.hot-footage {
		bottom: 0;
		overflow: hidden;
		position: fixed;
		width: 311px;
		z-index: 8;
	}
	.hot-footage .dottle {
		border-top: 1px solid #CCCCCC;
	}
	.hot-title {
		margin-top: 12px;
	}
	.hot-icon {
		background: none repeat scroll 0 0 #FF6600;
		float: left;
		height: 28px;
		margin-top: 10px;
		overflow: hidden;
		width: 4px;
	}
	.hot-title h3 {
		color: #333333;
		font-family: "Microsoft yahei";
		font-size: 30px;
		font-weight: 500;
		padding-left: 10px;
	}
	.hot-list {
		margin-top: 5px;
		overflow: hidden;
		width: 311px;
	}
	.hot-list li {
		display: inline;
		float: left;
		height: 150px;
		margin: 5px 10px 0 0;
		overflow: hidden;
		width: 150px;
	}
	.hot-list li.last {
		margin-right: 0;
	}
	.hot-list li a {
		display: block;
		height: 100px;
		overflow: hidden;
		position: relative;
		width: 150px;
	}
	.hot-list .icon-player {
		background: url("http://img02.taobaocdn.com/tps/i2/T1J5FFXy8cXXaiphQj-60-145.png") no-repeat scroll 0 -40px rgba(0, 0, 0, 0);
		height: 50px;
		left: 10px;
		overflow: hidden;
		position: absolute;
		top: 40px;
		width: 50px;
		z-index: 10;
	}
	.hot-date {
		color: #666666;
		font-family: "Tahoma";
		height: 18px;
		line-height: 18px;
		margin-top: 5px;
	}
	.hot-desc a:hover {
		text-decoration: none;
	}
  </style>

 3. 當然更依賴於kissy哦 要引入kissy:<script src="http://a.tbcdn.cn/??s/kissy/1.2.0/kissy-min.js"></script>

 現在框架已經搭建好了,接下來我來分析下 當時我寫的JS程式碼。首先我想渲染左側年份列表出來 及右側控制軸渲染出來 如下圖:

 

所以上面的程式碼是渲染年份列表的 如下:

/* 
             * 發jsonp請求 
             * 1.渲染列表中的所有年份HTML出來
             * 2.把控制軸上的所有年份及月份及條目列表中的年份渲染出來
             */
             S.jsonp(_config.year_url + "&timestamp="+S.now(),function(data){
                _renderYear(data);
             });
             function _renderYear(data) {
                if(data.isSuccess) {
                    var yearlists = data.list,
                        yearHTML = '',
                        liHTML = '';
                    /*
                     * 渲染列表中的所有年份HTML出來
                     */
                     for(var i = 0, ilen = yearlists.length; i < ilen; i+=1) {
                        yearHTML += '<div class="J_Year_Month">'+
                                        '<div class="tao-header-title J_Header_Title">'+
                                            '<span data-year="'+yearlists[i].year+'" class="J_Year">'+yearlists[i].year+'<i>年</i></span>'+
                                        '</div>' + 
                                        '<div class="tao-dottle-top"></div>' + 
                                        '<div class="J_Video_Block"></div>' + 
                                    '</div>';
                     }
                     var recentlyYear = yearlists[0].year;
                     D.html(D.get(_config.videoContainer),yearHTML);
                     /*
                      * 把控制軸上的所有年份渲染出來
                      */
                     for(i = 0,itemLen = yearlists.length; i < itemLen; i++){
                        liHTML += '<li data-year="'+yearlists[i].year+'" class="itemList">' + 
                                     '<a class="yearlink" href="#">'+yearlists[i].year+'年</a>' +
                                     '<ul class="timelinenav-mpanel"></ul>' +  
                                   '</li>';
                     }
                     D.html(D.get(_config.listContainer),liHTML,false,function(){
                        D.addClass(D.get(_config.listContainer + " li"),_config.activeCls);
                        D.attr(D.get(_config.listContainer + " li"),{"index":"1"});
                     });

                     /*
                      * 分別渲染各個年份中的月份
                      */
                     var monthContainers = D.query(".timelinenav-mpanel"); 
                     for(var m = 0, mlen = monthContainers.length; m < mlen; m+=1) {
                        var ulHTML = "";
                        for(var k = 0,subItems = yearlists[m].month.length; k < subItems; k+=1){
                            ulHTML += '<li data-year="'+yearlists[m].year+'" data-month="'+yearlists[m].month[k]+'" class="itemHover">' + 
                                         '<a class="monthlink" href="#">'+yearlists[m].month[k]+'月</a>' +
                                       '</li>';
                        }
                        D.html(monthContainers[m],ulHTML,false,function(){
                            
                            var headerTitle = D.query(".J_Year"),
                                itemLists = D.query(".itemList"),
                                videoBlocks = D.query(".J_Video_Block");
                            // 預設時候 當前年份 最近月份高亮
                            D.addClass(D.get(".itemHover"),_config.highlightCls);
                        });
                     }

4. 接著發請求 把左側列表中最近年份 下的所有月份渲染出來 如下程式碼可以實現:

var self = this,
                _config = self.config;
            var allYears = D.query(".J_Year_Month");
            
            S.each(allYears,function(everyYear,index){
                var jYear = D.get(".J_Year",everyYear),
                    jDataYear = D.attr(jYear,"data-year"),
                    jTextArea = D.get(".J_Video_Block",everyYear);
                S.jsonp(_config.list_url+"&group="+jDataYear+"&timestamp="+S.now(),function(data){
                    if(data.isSuccess){
                        var dataLists = data.list,
                            dataContainer = "";
                        for(var x=0,xlen=dataLists.length; x<xlen; x+=1){
                            var tempGroupId = dataLists[x].group_id;
                            dataContainer +='<div class="tao-video-content">'+
                                                '<div class="addBlock"></div>' +
                                                '<div class="left-date" videoMonth="'+tempGroupId.substring(4,6)+'">'+
                                                    '<span><i class="J_Month" M_year="'+tempGroupId.substring(0,4)+'">'+tempGroupId.substring(4,6)+'</i>月</span>'+
                                                    '<span><i class="J_Day">'+tempGroupId.substring(6,8)+'</i>日</span>'+
                                                '</div>'+
                                                '<div class="tao-line"></div>'+
                                                '<div class="tao-inner-content">'+
                                                    '<div class="tao-inner-block">'+
                                                        '<div class="inner-left">'+
                                                            '<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'" class="alink">'+
                                                                '<img src="'+dataLists[x].video_pic.replace("/0","/1")+'" alt="">'+
                                                                '<span class="icon-player"></span>'+
                                                            '</a>'+
                                                        '</div>'+
                                                        '<div class="inner-right">'+
                                                            '<p class="inner-date">'+tempGroupId.substring(0,4)+'-'+tempGroupId.substring(4,6)+'-'+tempGroupId.substring(6,8)+'</p>'+
                                                            '<p class="inner-title">' +
                                                                '<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'">'+dataLists[x].subject+'</a>'+
                                                            '</p>'+
                                                            '<div class="inner-content">'+dataLists[x].content+'</div>'+
                                                        '</div>'+
                                                    '</div>'+
                                                '</div>'+
                                             '</div>';
                        }
                        if(flag == 'hover') {
                            (new DataLazyload(everyYear, {diff: 200})).addCallback(everyYear, function(){
                                self._isDelayLoad(jTextArea,dataContainer,index);
                            });
                        }

我上面的程式碼也有個小缺點 就是說頁面一開啟的時候 聯絡發了四個請求 把所有年份都渲染出來 但是資料並沒有到頁面上來 還是以前的邏輯 當滾動條滾動到離還有200畫素的時候 再把資料渲染到頁面上來。

5. 接著再做了以下事情:

     1.  列表中的年份和控制軸中的年份相等時候 控制軸的年份展開。

   2.  當滾動到列表中年份中的月份時候 對應的控制軸月份也要相應的變化(如高亮等),隨著滑鼠滾動。

   3.  點選控制軸任一年份時候 滾動到條目列表中相對應的年份來.

程式碼如下:

   

var self = this,
				_config = self.config,
				_cache = self.cache;

			D.html(jTextArea,dataContainer,false,function(){
				var	itemLists = D.query(_config.listContainer + " .itemList"),
					itemHover = D.query(".itemHover",itemLists[index]),
					jmonths = D.query(".J_Month",jTextArea[index]),
					headerTitle = D.query(".J_Year");
				// 預設時候 當前年份 最近月份高亮
				D.addClass(D.get(".itemHover"),_config.highlightCls);
	
				var storage = function(itemFChar){
					for(var i = 0, ilen = itemHover.length; i < ilen; i+=1){
						 var itemMonth = D.attr(itemHover[i],"data-month");	
						 if(itemMonth == itemFChar){
							KISSY.all(itemHover[i]).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
						}
					}
				};
				E.on(window,'scroll',function(){
					if(D.hasClass(D.get(_config.listContainer),'isScroll')){
						var wTop = D.offset(window).top;
						/*** 列表中的年份和控制軸中的年份相等時候 控制軸的年份展開 ***/
						for(var m=0,mlen=headerTitle.length; m<mlen; m+=1){
							var headerTop = D.offset(headerTitle[m]).top,
								headAttr = D.attr(headerTitle[m],"data-year"),
								itemAttr = D.attr(itemLists[m],"data-year");
							if(headerTop <= wTop){
								if(headAttr == itemAttr){
									KISSY.all(itemLists[m]).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
								}
							}
						}
						/*** 當滾動到列表中年份中的月份時候 對應的控制軸月份也要相應的變化(如高亮等) **/
						for(var nn = 0, nlen = jmonths.length; nn < nlen; nn+=1){
							var jmonthTop = D.offset(jmonths[nn]).top;
							if(jmonthTop <= wTop){
								
								var itemVal = D.html(jmonths[nn]),
								// 轉換02 -> 2 
								itemFChar = itemVal.substring(0,1);
								if(itemFChar == 0){
									itemFChar = itemVal.substring(1,2);
								}else{
									itemFChar = itemVal.substring(0,2);
								}
								storage(itemFChar);
							}
						}
					}
				});
				// 點選控制軸任一年份時候 滾動到條目列表中相對應的年份來
			   var	itemLists = D.query(_config.listContainer + " .itemList");
			   S.each(itemLists,function(item,index){
				   var innerIndex;
				   E.on(item,'click',function(e){
					   e.preventDefault();
					   e.halt();
					   innerIndex = index;
					   var scrollTimer,
						   DELAY = 0.3;
					   !D.hasClass(KISSY.all(this),_config.activeCls) && KISSY.all(this).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
					   
					   if(!D.hasClass(KISSY.all(this),"isClick")){
						   D.addClass(KISSY.all(this),"isClick");
					   }
					   var curThis = KISSY.all(this);
					   // 刪除類
					   D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					   var headerTop = D.offset(headerTitle[index]).top;
					   scrollTimer && scrollTimer.cancel();
					   scrollTimer = S.later(function(){
							KISSY.all("html,body").animate({"scrollTop":headerTop},DELAY,'easeBothStrong',function(){
								D.removeClass(D.query(".itemHover"),_config.highlightCls);
								!D.hasClass(D.get(".itemHover",curThis),_config.highlightCls) && D.addClass(D.get(".itemHover",curThis),_config.highlightCls);
								!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
							});
						},DELAY);
						_config.yearCallback && S.isFunction(_config.yearCallback) && _config.yearCallback();
						self._clickMenu(itemLists,innerIndex);
				   });
				   if(innerIndex == undefined){
					  innerIndex = 0;
					  self._clickMenu(itemLists,innerIndex);
				   }
			   });

 6. 最後 點選控制軸當前年份中的月份時候 滾動到當前的月份的地方。程式碼如下:

 

// 點選控制軸當前年份中的月份時候 滾動到當前的月份的地方。
		    var itemHovers = D.query(".itemHover",KISSY.all(itemLists[innerIndex]));
			S.each(itemHovers,function(itemHover,curIndex){
				E.on(itemHover,'click',function(e){
					
					e.halt();
					var itemMonth = D.attr(KISSY.all(itemHover),"data-month");
					var tempArr = [],
						scrollTimer,
						DELAY = 0.1;
					console.log(itemMonth);
					var	curMonths = D.query(".left-date",D.query(".J_Year_Month")[innerIndex]);
					 // 刪除類
					D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					KISSY.all('.itemHover').removeClass(_config.highlightCls);
					KISSY.all(this).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
					for(var i=0; i<curMonths.length; i+=1){
						var itemVal = D.attr(curMonths[i],"videoMonth");
						// 轉換02 -> 2 
						var itemFChar = itemVal.substring(0,1);
						if(itemFChar == 0){
							itemFChar = itemVal.substring(1,2);
						}else{
							itemFChar = itemVal.substring(0,2);
						}
						tempArr.push(itemFChar);
					}
					for(var j=0; j<tempArr.length; j+=1){
						var tempV = tempArr[j];
						if(itemMonth == tempArr[j]){
							var mtop = D.offset(curMonths[j]).top;
							scrollTimer && scrollTimer.cancel();
							scrollTimer = S.later(function(){
								KISSY.all("html,body").animate({"scrollTop":mtop},DELAY,'easeBothStrong',function(){
									!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
								});
							},DELAY);
							break; // 此break是當陣列裡面的月份有多個相同的時候 只取第一個月份
						}
					}
					_config.monthCallback && S.isFunction(_config.monthCallback) && _config.monthCallback();

 

  綜合以上 所有JS程式碼如下:

 

KISSY.add('timeline/nav',function(S,DataLazyload){
	var D = S.DOM,
		E = S.Event;

	function TimeLineNav() {

		this.config = {
			year_url       :'http://bbs.hitao.com/apps.php?q=tvshow&m=video_years',    //所有年份URL
			list_url       :'http://bbs.hitao.com/apps.php?q=tvshow&m=video_group',    // 時間軸list列表 URL
			delay          : 100,                                                      // 延遲time
			highlightCls   :'highlight',                                               // 高亮類
			fixedCls       :'mod-fixed',                                               // fixed類
			activeCls      :'active',                                                  // 當前active class
			videoContainer :'#J_Video_Left',                                           // 左側視訊容器
			listContainer  :'#timelinenavpanel',                                       // 控制軸容器 
			yearCallback   : null,                                                     // 點選某一項年份時的回撥函式
			monthCallBack  : null                                                      // 點選某一項月份時候回撥
		};

		this.cache = {
			
		};
	}
	TimeLineNav.prototype = {
		init: function(options) {
			this.config = S.augment(this.config,options || {});
            var self = this,
                _config = self.config;
			/* 
			 * 發jsonp請求 
			 * 1.渲染列表中的所有年份HTML出來
			 * 2.把控制軸上的所有年份及月份及條目列表中的年份渲染出來
			 */
			 S.jsonp(_config.year_url + "&timestamp="+S.now(),function(data){
				_renderYear(data);
			 });
			 function _renderYear(data) {
				if(data.isSuccess) {
					var yearlists = data.list,
						yearHTML = '',
						liHTML = '';
					/*
					 * 渲染列表中的所有年份HTML出來
					 */
				     for(var i = 0, ilen = yearlists.length; i < ilen; i+=1) {
						yearHTML += '<div class="J_Year_Month">'+
										'<div class="tao-header-title J_Header_Title">'+
											'<span data-year="'+yearlists[i].year+'" class="J_Year">'+yearlists[i].year+'<i>年</i></span>'+
										'</div>' + 
										'<div class="tao-dottle-top"></div>' + 
										'<div class="J_Video_Block"></div>' + 
									'</div>';
					 }
					 var recentlyYear = yearlists[0].year;
					 D.html(D.get(_config.videoContainer),yearHTML);
				     /*
					  * 把控制軸上的所有年份渲染出來
					  */
					 for(i = 0,itemLen = yearlists.length; i < itemLen; i++){
						liHTML += '<li data-year="'+yearlists[i].year+'" class="itemList">' + 
									 '<a class="yearlink" href="#">'+yearlists[i].year+'年</a>' +
									 '<ul class="timelinenav-mpanel"></ul>' +  
								   '</li>';
					 }
					 D.html(D.get(_config.listContainer),liHTML,false,function(){
						D.addClass(D.get(_config.listContainer + " li"),_config.activeCls);
						D.attr(D.get(_config.listContainer + " li"),{"index":"1"});
					 });

					 /*
					  * 分別渲染各個年份中的月份
					  */
					 var monthContainers = D.query(".timelinenav-mpanel"); 
					 for(var m = 0, mlen = monthContainers.length; m < mlen; m+=1) {
						var ulHTML = "";
						for(var k = 0,subItems = yearlists[m].month.length; k < subItems; k+=1){
							ulHTML += '<li data-year="'+yearlists[m].year+'" data-month="'+yearlists[m].month[k]+'" class="itemHover">' + 
										 '<a class="monthlink" href="#">'+yearlists[m].month[k]+'月</a>' +
									   '</li>';
						}
						D.html(monthContainers[m],ulHTML,false,function(){
							
							var headerTitle = D.query(".J_Year"),
								itemLists = D.query(".itemList"),
								videoBlocks = D.query(".J_Video_Block");
							// 預設時候 當前年份 最近月份高亮
							D.addClass(D.get(".itemHover"),_config.highlightCls);
						});
					 }
					 
					self._query('hover');
				}else {
					return;
				}
			 }
		    /*
			 * 1.滾動條先滾動 當離頂部距離差距不大的時候 使右側選單固定在頂部20px;
			 */
			var timelineTop = D.offset(".mod-timelinenav").top,
				scrollTimer;
			E.on(window,'scroll',function(){
				scrollTimer && scrollTimer.cancel();
				scrollTimer = S.later(function(){
					var windowTop = D.offset(window).top;
					if(timelineTop <=windowTop){
						D.addClass(".mod-timelinenav","mod-fixed");
					}else{
						D.removeClass(".mod-timelinenav","mod-fixed");
					}
				},_config.delay);
			});
			
		},
		_query: function(flag) {
			var self = this,
				_config = self.config;
			var allYears = D.query(".J_Year_Month");
			
			S.each(allYears,function(everyYear,index){
				var jYear = D.get(".J_Year",everyYear),
					jDataYear = D.attr(jYear,"data-year"),
					jTextArea = D.get(".J_Video_Block",everyYear);
				S.jsonp(_config.list_url+"&group="+jDataYear+"&timestamp="+S.now(),function(data){
					if(data.isSuccess){
						var dataLists = data.list,
							dataContainer = "";
						for(var x=0,xlen=dataLists.length; x<xlen; x+=1){
							var tempGroupId = dataLists[x].group_id;
							dataContainer +='<div class="tao-video-content">'+
												'<div class="addBlock"></div>' +
												'<div class="left-date" videoMonth="'+tempGroupId.substring(4,6)+'">'+
													'<span><i class="J_Month" M_year="'+tempGroupId.substring(0,4)+'">'+tempGroupId.substring(4,6)+'</i>月</span>'+
													'<span><i class="J_Day">'+tempGroupId.substring(6,8)+'</i>日</span>'+
												'</div>'+
												'<div class="tao-line"></div>'+
												'<div class="tao-inner-content">'+
													'<div class="tao-inner-block">'+
														'<div class="inner-left">'+
															'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'" class="alink">'+
																'<img src="'+dataLists[x].video_pic.replace("/0","/1")+'" alt="">'+
																'<span class="icon-player"></span>'+
															'</a>'+
														'</div>'+
														'<div class="inner-right">'+
															'<p class="inner-date">'+tempGroupId.substring(0,4)+'-'+tempGroupId.substring(4,6)+'-'+tempGroupId.substring(6,8)+'</p>'+
															'<p class="inner-title">' +
																'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'">'+dataLists[x].subject+'</a>'+
															'</p>'+
															'<div class="inner-content">'+dataLists[x].content+'</div>'+
														'</div>'+
													'</div>'+
												'</div>'+
											 '</div>';
						}
						if(flag == 'hover') {
							(new DataLazyload(everyYear, {diff: 200})).addCallback(everyYear, function(){
								self._isDelayLoad(jTextArea,dataContainer,index);
							});
						}
					}else {
						return;
					}
				});
				
			});
		},
		_isDelayLoad: function(jTextArea,dataContainer,index) {
			var self = this,
				_config = self.config,
				_cache = self.cache;

			D.html(jTextArea,dataContainer,false,function(){
				var	itemLists = D.query(_config.listContainer + " .itemList"),
					itemHover = D.query(".itemHover",itemLists[index]),
					jmonths = D.query(".J_Month",jTextArea[index]),
					headerTitle = D.query(".J_Year");
				// 預設時候 當前年份 最近月份高亮
				D.addClass(D.get(".itemHover"),_config.highlightCls);
	
				var storage = function(itemFChar){
					for(var i = 0, ilen = itemHover.length; i < ilen; i+=1){
						 var itemMonth = D.attr(itemHover[i],"data-month");	
						 if(itemMonth == itemFChar){
							KISSY.all(itemHover[i]).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
						}
					}
				};
				E.on(window,'scroll',function(){
					if(D.hasClass(D.get(_config.listContainer),'isScroll')){
						var wTop = D.offset(window).top;
						/*** 列表中的年份和控制軸中的年份相等時候 控制軸的年份展開 ***/
						for(var m=0,mlen=headerTitle.length; m<mlen; m+=1){
							var headerTop = D.offset(headerTitle[m]).top,
								headAttr = D.attr(headerTitle[m],"data-year"),
								itemAttr = D.attr(itemLists[m],"data-year");
							if(headerTop <= wTop){
								if(headAttr == itemAttr){
									KISSY.all(itemLists[m]).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
								}
							}
						}
						/*** 當滾動到列表中年份中的月份時候 對應的控制軸月份也要相應的變化(如高亮等) **/
						for(var nn = 0, nlen = jmonths.length; nn < nlen; nn+=1){
							var jmonthTop = D.offset(jmonths[nn]).top;
							if(jmonthTop <= wTop){
								
								var itemVal = D.html(jmonths[nn]),
								// 轉換02 -> 2 
								itemFChar = itemVal.substring(0,1);
								if(itemFChar == 0){
									itemFChar = itemVal.substring(1,2);
								}else{
									itemFChar = itemVal.substring(0,2);
								}
								storage(itemFChar);
							}
						}
					}
				});
				// 點選控制軸任一年份時候 滾動到條目列表中相對應的年份來
			   var	itemLists = D.query(_config.listContainer + " .itemList");
			   S.each(itemLists,function(item,index){
				   var innerIndex;
				   E.on(item,'click',function(e){
					   e.preventDefault();
					   e.halt();
					   innerIndex = index;
					   var scrollTimer,
						   DELAY = 0.3;
					   !D.hasClass(KISSY.all(this),_config.activeCls) && KISSY.all(this).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
					   
					   if(!D.hasClass(KISSY.all(this),"isClick")){
						   D.addClass(KISSY.all(this),"isClick");
					   }
					   var curThis = KISSY.all(this);
					   // 刪除類
					   D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					   var headerTop = D.offset(headerTitle[index]).top;
					   scrollTimer && scrollTimer.cancel();
					   scrollTimer = S.later(function(){
							KISSY.all("html,body").animate({"scrollTop":headerTop},DELAY,'easeBothStrong',function(){
								D.removeClass(D.query(".itemHover"),_config.highlightCls);
								!D.hasClass(D.get(".itemHover",curThis),_config.highlightCls) && D.addClass(D.get(".itemHover",curThis),_config.highlightCls);
								!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
							});
						},DELAY);
						_config.yearCallback && S.isFunction(_config.yearCallback) && _config.yearCallback();
						self._clickMenu(itemLists,innerIndex);
				   });
				   if(innerIndex == undefined){
					  innerIndex = 0;
					  self._clickMenu(itemLists,innerIndex);
				   }
			   });	
			});
		},
		_clickMenu: function(itemLists,innerIndex) {
			var self = this,
				_config = self.config;
			if(innerIndex == undefined){
				return;
			}
			// 點選控制軸當前年份中的月份時候 滾動到當前的月份的地方。
		    var itemHovers = D.query(".itemHover",KISSY.all(itemLists[innerIndex]));
			S.each(itemHovers,function(itemHover,curIndex){
				E.on(itemHover,'click',function(e){
					
					e.halt();
					var itemMonth = D.attr(KISSY.all(itemHover),"data-month");
					var tempArr = [],
						scrollTimer,
						DELAY = 0.1;
					console.log(itemMonth);
					var	curMonths = D.query(".left-date",D.query(".J_Year_Month")[innerIndex]);
					 // 刪除類
					D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					KISSY.all('.itemHover').removeClass(_config.highlightCls);
					KISSY.all(this).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
					for(var i=0; i<curMonths.length; i+=1){
						var itemVal = D.attr(curMonths[i],"videoMonth");
						// 轉換02 -> 2 
						var itemFChar = itemVal.substring(0,1);
						if(itemFChar == 0){
							itemFChar = itemVal.substring(1,2);
						}else{
							itemFChar = itemVal.substring(0,2);
						}
						tempArr.push(itemFChar);
					}
					for(var j=0; j<tempArr.length; j+=1){
						var tempV = tempArr[j];
						if(itemMonth == tempArr[j]){
							var mtop = D.offset(curMonths[j]).top;
							scrollTimer && scrollTimer.cancel();
							scrollTimer = S.later(function(){
								KISSY.all("html,body").animate({"scrollTop":mtop},DELAY,'easeBothStrong',function(){
									!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
								});
							},DELAY);
							break; // 此break是當陣列裡面的月份有多個相同的時候 只取第一個月份
						}
					}
					_config.monthCallback && S.isFunction(_config.monthCallback) && _config.monthCallback();
				});
			});
		}
	};

	return TimeLineNav;
},{requires:['datalazyload']});

 

  JS初始化如下 :
  KISSY.use("timeline/nav",function(S,obj){
       new obj().init({});
 });

相關文章