论坛首页 Web前端技术论坛

【JS优化系列】一个通用公告系统的实现

浏览 1960 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-08-17   最后修改:2009-09-12

       之前一篇《【JS优化系列】从一个计时器的写法探讨js多种实现方式的优劣》的讨论让我学到不少东西,现在再来一篇,抛砖引玉。

 

       站点的很多页面经常需要发一些公告,而每次发公告都需要开发同学手工来操作是很麻烦的,而且经常不够实时。因此写了一个通用公告系统,希望能将这份工作交由产品同学来操作。这里只写了“小黄条”一种形式的公告,其他形式实现方法类似。实现了可以“定时自动关闭”,“所有页面每次打开都显示小黄条”,“仅在第一次打开的页面显示一次”,“用户手动关闭后不再显示”功能。以此基本能满足日常运营需求。

      先将代码和实现方式贴出,邀请大家一起探讨优化。

 

/**
 * 通用公告系统
 * 
 * @package    pub_notice.js
 * @author     jessezhang <jianguang.qq@gmail.com>
 * @date       2009-08-15
 * @version    1.0.0
 */

var LIB = LIB || {};
LIB .pubNotice = (function(){
	
	var $id = function(id){return document.getElementById(id);}
	var $ = LIB ;
	
	/**
	 * 小黄条
	 * 	 
	 * @access public
	 * @param {json} json 小黄条属性
	 */
	function yellowTips(json){
		this._id = json["id"];
		this._text = json["text"];
		this._showType = json["showType"];
		this._timeout = json["timeout"];
		this._domId = "QQVIP_pubNotice_yellowTips_" + json["id"];
		this._timer = null;
	}
	
	yellowTips.prototype = (function(){	
									 
		/**
		 * create一个小黄条
		 * 
		 * @access public
		 */	 				 
		function create(){	
			if(!_checkShowType.call(this))return ;
			//container标签为必须,诺没有container,则不显示小黄条						
			if(!$id("container"))return;
			
			var _nBox = document.createElement("div");
			_nBox.id = this._domId;
			_nBox.className = "bulletin";
			_nBox.innerHTML = "<button type=\"button\" class=\"bt_close_bulletin\" title=\"关闭\" onclick=\"javascript:document.getElementById('"+this._domId +"').style.display='none';QQVIP.cookie.set('" + this._domId + "', '2');\">X</button>" + this._text;
			document.body.insertBefore(_nBox,$id("container"));
			this._timeout && this.hide(this._timeout);
			$.cookie.set(this._domId,"1");//1:表示已经显示过该小黄条
		}
		
		/**
		 * 显示小黄条
		 * 
		 * @access public
		 */	 
		function show(){
			$id(this.domId).style.display = "";
		}
		
		/**
		 * 隐藏小黄条的接口
		 * 
		 * @access public
		 */		
		function hide() {
			var _this = this;
			if (this._timeout) {
				this._timer && clearTimeout(this._timer);
				this._timer = setTimeout(function(){_hide.call(_this);}, this._timeout);
			} else {
				_hide.call(_this);
			}
		}
		
		/**
		 * 内部实现隐藏小黄条
		 * 
		 * @access private
		 */	
		function _hide(){
			this._timer && clearTimeout(this._timer);
			$id(this._domId).style.display = "none";
		}	
		
		/**
		 * showType : 显示方式
		 * 1:所有页面每次打开都显示
		 * 2:只在第一次打开的页面显示一次
		 * 3:用户手动关闭后不显示
		 *
		 * cookieValue : cookie存储的状态
		 * 1:已经显示过
		 * 2:用户手动关闭
		 */	
		function _checkShowType(){
			if(this._showType == "1") return true;
			var cookieValue = $.cookie.get(this._domId);
			return (this._showType == "2" && cookieValue != "1" && cookieValue != "2") || (this._showType == "3" && cookieValue != "2");
		}
		
		return {
			create : create, 
			show : show, 
			hide : hide
		}		
	})()
	
	/**
	 * 浮出层,建设中...
	 * 
	 */
	function floatLayer(obj){}
	
	/**
	 * 弹出窗口,建设中...
	 * 
	 */
	function openWindow(obj){}
	
	/**
	 * 将设置的url转化成验证页面地址的正则表达式
	 * 
	 * @access private
	 * @param {istring} url 设置的url
	 * @return {RegExp} 验证页面地址的正则表达式
	 */
	 
	function _regURL(url){
		if (/^\^/.test(url)) {
			//以符号"^"开头的url都看成本身已经是正则表达式的形式了,不需要再处理
			return new RegExp(url);
		} else {
			//不是以符号"^"开头的url都需要处理成正则表达式的形式,
			//主要对符号"/"和index.html、index.htm、index.php进行处理,		
			//使得"http://vip.lib.com/index.html"、"http://vip.lib.com/"都可以被正确识别
			var RegStr = url.replace(/(^[\w-:\/\.]*).*/, function($0, $1){
				var ret = $1.replace(/\//g, "\/").replace(/\?/g, "\?");			
				var reg = new RegExp("(index.html|index.htm|index.php)$");
				if (reg.test($1)) {
					ret = ret.replace(reg, function(a,b){
						return 	"(("+b+")+|$|\\?|\\#)";						  
					});
				} else {
					ret = $1+"((index.html|index.htm|index.php)+|$|\\?|\\#)";
				}
				return ret;
			});
			return new RegExp(RegStr);
		}
	}
	
	/**
	 * 判断当前页面的url是否符合要求
	 * 
	 * @access public
	 * @param {istring} str 设置的验证url的字符串
	 */
	function checkUrl(str){
		var loaction = window.location;
		str = str.replace(/^\||\|$/g,"");
		var urls = str.split("|");
		for(var j=0; j<urls.length; j++){
			if(_regURL(urls[j]).test(loaction)){			
				return true;
			}
		}
		return false;
	}
		 
	return {
		yellowTips : yellowTips,
		floatLayer : floatLayer,
		openWindow : openWindow,
		checkUrl : checkUrl
	};
})();

 (function(){
	var yellowTips = [
		{id:1, url:'^http://vip.LIB .com/|', text:'<strong>LIB 宣:</strong><p>这是世界上最强大的紧急公告系统!</p>', showType:1, timeout:3*1000},
		{id:2, url:'http://vip.LIB .com/mall/mall.php|http://vip.LIB .com/freedom_act/act.html|http://vip.LIB .com/my_status/my_status_index.php', text:'<strong>LIB 专区问题</strong><p>LIB 专区问题</p>', showType:2, timeout:0*1000},
		{id:3, url:'http://vip.LIB .com/qq.html|http://vip.LIB .com/life.html|', text:'<strong>[LIB ]</strong><p>LIB 频道,生活公告ffff</p>', showType:3, timeout:0*1000}
	]
	for(var i=0; i<yellowTips.length; i++){
		if(LIB.pubNotice.checkUrl(yellowTips[i]["url"])){
			new LIB.pubNotice.yellowTips(yellowTips[i]).create();
		}
	}
})()

      目前的实现方式是,所有页面都在自身加载完成之后去加载这段代码。代码会通过页面的url来判断是否显示公告,以及显示哪几条公告。而设置的时候有两种方式,一种是输入特定页面的完全url,另一种是通过正则来匹配。在本实现中以传入的url是否以“^”符号其起始来判断是否当正则来处理(这种方式好坏大家可以一起探讨),如“^http://vip.lib.com/”表示发布到vip.lib.com域名下的所有页面,“http://vip.lib.com/”或者“http://vip.lib.com/index.html”表示仅仅发布到lib首页一个页面。

      这里的代码将由管理后台生成,若没有没有公告,则所有代码为空,以节省流量。

      在本例中应该有很多地方可以优化的,希望大家一起探讨优化。比如_regURL()这个函数的实现,我并没有做很多的考虑,肯定有很多可以优化的地方。还有实现方式上也有很多地方值得探讨,比如这样做所有页面都多了个请求,所有页面都会引入所有的公告内容,这样实现是否是最好的。代码是由管理后台生成的,那么产品同学输入内容的,在后台输出的时候是不是需要过滤处理那些特殊字符,等等。。。还有很多其他需要周全考虑的地方。

      希望大家一起来探讨,让代码达到最“优雅”。当然大家的探讨不仅仅是代码上,还可以是整个公告实现的方式上的。

 

 

 

 

【本人发帖抛砖引玉,希望能够引出更多的“玉”来,希望所写的每一段代码都能够得到一种最“优雅”的实现方式。以后本人会抛出更多的“砖”,希望能引来更多的“玉”,以供大家一起学习进步】

 

论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics