代码改变世界

历史回顾日历_JS脚本

2011-03-28 13:42  rocdu  阅读(612)  评论(0编辑  收藏  举报

做了一个历史回顾日历脚本,以下是需求及代码。

交互需求:
1、切换年份标签,成生相关日历数据(做缓存优化)
2、根据日历串出对应的历史库链接地址
3、给月份绑定跳转锚点
4、根据域名回填频道名称
5、开放当前月个性化操作接口

效果展示:


复制代码生成HTML文件查看效果

脚本源码:

/**
 * @author rocdu
 * @desc 历史回顾日历
 * @dependency jquery.js
 */
;(function($){
    var now = new Date(),        // 获取当前日期
        dataCache = new Array(); // 缓存数据数组
    /**
     * 日历类
     * @param {Obj} _data
     * @param {fun} _cbk
     */
    window.Calendar = function(_data, _cbk){
        var that = this;

        /* 获取当前日期 */
        this.date = {
            year: now.getFullYear(),   // 当前年份
            month: now.getMonth() + 1, // 当前月份,从1开始
            week: now.getDay(),        // 当前星期,从0开始
            today: now.getDate()       // 当前日期
        };
		
		/* 获取回调方法 */
        this.cbk = _cbk;
		
        $(document).ready(function(){ // DOM加载完成
			/* 获取数据回填ID */
			that.id = {
				year: $('#' + _data.id.year),      // 年代
				data: $('#' + _data.id.data),      // 日历数据
				place: $('#' + _data.id.place),    // 月份锚点
				channel: $('#' + _data.id.channel) // 频道
			};
			
			/* 执行初始化 */
			that.init(_data);
		});
	};
	Calendar.prototype = {
		/**
		 * 初始化
		 * @param {Obj} _data
		 */
		init: function(_data){
			var channelName = document.domain.split('.')[0],                      // 获取二级域名字符
			    url = _data.linkPrefixion || 'http:\/\/' + document.domain + '/', // 配URL给日历链接
				beginYear = _data.beginYear || 2000;                              // 初始年份
			
			/* 回填频道名称 */
			for (var name in _data.domainList){                            // 遍历域名字典
				if (name == channelName){                                  // 域名匹配
					this.id.channel.html(_data.domainList[name] + '频道'); // 回填频道名称
					break;                                                 // 退出循环
				}
			};
			
			/* 执行回填年份 */
			this.addYear(url, beginYear);
			
			/**
			 * 激活展开今年的日历
			 * 配置initThisYear = true执行,
			 * = false不执行.
			 * 不配置,默认为true
			 */
			(_data.initThisYear == undefined || _data.initThisYear)
			&& this.id.year.trigger("initThisYear");
		},
		
		/**
		 * 回填年份HTML
		 * @param {str} _url
		 * @param {int} _initYear
		 */
		addYear: function(_url, _beginYear){
			var HTML = '',
				that = this,
				thisYear = this.date.year, // 当前年份
				yearID = this.id.year,     // 年份回填ID
				dataID = this.id.data,     // 日历数据回填ID
				placeID = this.id.place;   // 锚点回填ID
			
			/**
			 * 回填年份HTML
			 * 从当前年份到初始年份
			 */
			while (thisYear >= _beginYear){
				HTML += '<a href="javascript:\/\/">' + thisYear + '<\/a>';
				thisYear --;
			};
			yearID.html(HTML);
			
			/* 给年份BTN代理mouseup事件 */
			yearID.find('a').live('mouseup', function(){
				var idx = $(this).index();
				
				/* 从缓存中获取数据并回填 */
				if (dataCache[idx] != undefined){
					dataID.html(dataCache[idx][0]);  // 回填日历
					placeID.html(dataCache[idx][1]); // 回填锚点
					return;                          // 退出循环
				};
				
				/* 创建日历HTML */
				that.calendarLayout($(this).html(), _url, idx);
			});
			
			/* 自定义当前年份激活事件 */
			yearID.bind("initThisYear",function(){
				$(this).find('a:eq(0)').mouseup();
			});
		},
		
		/**
		 * 创建日历HTML
		 * @param {str} _year
		 * @param {str} _url
		 */
		calendarLayout: function(_year, _url, _idx){
			var that = this,
				dataID = this.id.data,
				placeID = this.id.place,
				HTML_weeks = '', // 日历星期_HTML
				HTML_date = '';  // 日历日期_HTML
				
				/* 日历星期_HTML */
				HTML_weeks += '<div class="weeks"><ul>';
				HTML_weeks += '<li>星期日</li>';
				HTML_weeks += '<li>星期一</li>';
				HTML_weeks += '<li>星期二</li>';
				HTML_weeks += '<li>星期三</li>';
				HTML_weeks += '<li>星期四</li>';
				HTML_weeks += '<li>星期五</li>';
				HTML_weeks += '<li>星期六</li>';
				HTML_weeks += '</ul></div>';
			
			/* 倒空HTML数据 */
			dataID.html('');  // 日历
			placeID.html(''); // 锚点
			
			/* 日历月份_HTML */
			var HTML_month = function(_month){
				return '<div class="team"><h2><span>' + _year + '年'
				+ _month + '月</span><a name="m' + _month +'"> </a></h2>';
			};
			
			/**
			 * 回填日历数据
			 * 如果是当前年份循环到当前月份
			 * 否则循环全年12个月份
			 */
			for (var i = (_year == this.date.year ? this.date.month : 12); i > 0; i--){
				HTML_date = that.dateData(_year, i, _url);                             // 获取日历日期
				dataID.html(dataID.html() + HTML_month(i) + HTML_weeks + HTML_date);   // 回填日历
				placeID.html('<a href="#m' + i + '">' + i + '月</a>'+ placeID.html()); // 回填锚点
			};
			
			/* 当前年份下,有回调则执行回调 */
			_idx == 0 && this.cbk && this.cbk(this);
			
			/* 把日历数据和锚点数组缓存到数组中 */
			dataCache[_idx] = [dataID.html(),placeID.html()];
		},
		
		/**
		 * 创建日历日期HTML
		 * @param {str} _year
		 * @param {str} _month
		 * @param {str} _url
		 */
		dateData: function(_year, _month, _url){
			var HTML = '',
				HTML_li = '',                                  // 日期_HTML
				dateNum = 0,                                   // 本月日期个数
				month = +(_month) > 9 ? _month : '0' + _month, // 月份不足两位补'0'
				
				/**
				 * 获取本月的1日是星期几
				 * 格式 new Date(年/月/日).getDay()
				 */
			    oneDay = new Date(_year + '/' + month + '/01').getDay();
			
			/**
			 * 获取本月日期个数
			 * 2月闰年为29天,否则为28天
			 * 4,6,9,11月为30天
			 * 其它为31天
			 */
			if (_month == '2'){
				dateNum = _year % 4 == 0 ? 29 : 28; 
			}else if (_month == '4' || _month == '6' || _month == '9' || _month == '11'){
				dateNum = 30;
			}else{
				dateNum = 31;
			};
			
			/* 添补日历每月1日之前的空位 */
			for (var i = 1; i <= +(oneDay); i++){
				HTML_li += '<li></li>';
			};
			
			/* 生成日期数据 */
			for (var i = 1; i <= dateNum; i++){
				/* 给今天添加'today'样式 */
				if (_month == this.date.month && _year == this.date.year){
					i == +(this.date.today) ?
					HTML_li += '<li class="today">' : HTML_li += '<li>';
				}else{
					HTML_li += '<li>';
				};
				
				/**
				 * 创建日历数据的链接
				 * 日期不足两位补'0'
				 */
				HTML_li += '<a href="' + _url + _year + month + '/' + _year
				        + month + (i > 9 ? i : '0' + i) + '09.shtml' + '" target="_blank">';
				HTML_li += i;
				HTML_li += '</a></li>';
			};
			HTML += '<div class="date"><ul>';
			HTML += HTML_li;
			HTML += '</ul></div></div>';
			
			/* 返回日期HTML数据 */
			return HTML;
		}
	};
})(jQuery);

/**
 * 日历类实例化脚本
*/
;(function($){
    /* 域名对应中文字典 */
	var domainList = {
			news: '新闻',
			mil: '军事',
			sports: '体育',
			business: '财经',
			money: '理财',
			stock: '股票',
			fund: '基金',
			it: 'IT',
			digi: '数码',
			auto: '汽车',
			yule: '娱乐'
		};
	
	/**
	 * 日历类实例化脚本
	 * Calendar({
     *    id:{            // 数据回填ID(必选)
     *      year: str,    // 回填年份使用
     *      data: str,    // 回填日历数据使用
     *      place: str,   // 回填锚点使用
     *      channel: str, // 回填频道使用
     *    },
     *    linkPrefixion: str, // 日历链接域名,不填域名即默认为当前服务器域名(可选)
     *    beginYear: int,     // 日历初始年份,不填年份即默认从2000年初始(可选)
     *    domainList: obj,    // 获得域名对应中文字典,不配置则不回填频道名称(可选)
     *    initThisYear: bool  // 是否展开当前年份,不选默认为展开(可选)
     *  },
     *  cbk() // 回调函数,对当前月份做个性化操作(可选)
     *});		
	 */
	var myCalendar = new Calendar({
			id:{
				year: 'years',
				data: 'calendar',
				place: 'place',
				channel: 'channel'
			},
			linkPrefixion: 'http://www.sohu.com/',
			beginYear: 2000,
			domainList: domainList,
			initThisYear: true
		},function(_obj){ // 个性化当前月的操作方法
			var obj = _obj.id.data.find('.today'),
				HTML_today = '<span>' + obj.text() + '</span>';							
			obj.html(HTML_today)            // 给今天去链接
			.nextAll('li').each(function(){ // 给今天之后的日期去链接
				$(this).html($(this).text());
			});
		});
})(jQuery);