按照W3C的说法,INS和DEL元素是用来标记文档变化的:INS用于标记新插入文档的内容;DEL元素用于标记已经从文档中删除的内容。此外,还可以给这两个元素设置cite和datetime属性。其中,cite为一个URI,语义上用来解释文档发生变化的原因;而datetime则表示文档发生变化的时间。在平常的使用中,很少有人会给这两个标签添加以上的属性(自动添加不算),本文主要介绍通过Javascript以及这两个属性来实现增强型的INS和DEL:当用户鼠标悬停在更改标记之上时,弹出浮动层显示内容变更的时间以及提供一个指向变更依据的链接。 最终的效果请查看这里。

具体的实现可以参考以下的代码:

InsDelTool = (function(){
	//浮动层模板
	var panelTemplate = '[%changetype%]@%datetime%';
	//浮动层class
	var panelClassName = 'panel';
	return {
		render: function(){
			//得到所有的ins和del元素
			var ins = document.getElementsByTagName('ins');
			var del = document.getElementsByTagName('del');
			//创建浮动层
			if( ins.length || del.length ){
				this.panel = document.createElement('span');
				this.panel.className = panelClassName;
				this.panel.style.display = 'none';
				document.body.appendChild(this.panel);
			}
			else return;
			//注册事件
			this._registerEvent(ins);
			this._registerEvent(del);
			//当点击除浮动层以外的地方时隐藏浮动层
			var _me = this;
			document.body.onclick = function(e){
				e = e || window.event;
				_me._hide();
			};
			//点击浮动层上的链接时隐藏浮动层
			_me.panel.onclick = function(e){
				e = e || window.event;
				var target = e.srcElement || e.target;
				if( target.tagName.toLowerCase() == 'a' )
					_me._hide();
				//停止事件冒泡
				if( typeof e.cancelBubble != 'undefined' )
					e.cancelBubble = true;
				else
					e.stopPropagation();
			};
		},
		/*
		 * 显示浮动层
		 * @param { Integer } x 浮动层x坐标
		 * @param { Integer } y 浮动层y坐标
		 */
		_show: function(x,y){
			x = x || 0;
			y = y || 0;
			with(this.panel.style){
				display = 'block';
				left = x + 'px';
				top = y + 'px';
			}
		},
		//隐藏浮动层
		_hide: function(){
			this.panel.style.display = 'none';
		},
		/*
		 * 设置浮动层的内容
		 * @param { Integer } type 内容类型,0表示插入,1表示删除
		 * @param { String  } cite 引用URI
		 * @param { String  } datetime 日期
		 */
		_setPanelContent: function(type,cite,datetime){
			this.panel.innerHTML = panelTemplate.replace(/%(.+?)%/ig,function(a,b){
				switch(b){
					case 'changetype': return type  ? '删除' : '插入';
					case 'cite': return cite;
					case 'datetime': return datetime;
				}
			});
		},
		//给ins和del注册事件
		_registerEvent: function(els){
			var _me = this;
			for( var i = els.length - 1; i >= 0; i-- ){
				var el = els[i];
				el.onmouseover = (function(el){
					return function(e){
						e = e || window.event;
						//得到 cite 和 datetime
						var type = el.tagName.toLowerCase() == 'ins' ? 0 : 1;
						var cite = el.getAttribute('cite');
						var date = el.getAttribute('datetime');
						if( !cite && !date ) return;
						//设置内容
						_me._setPanelContent(type,cite,date);
						//计算panel的显示位置并显示panel
						var x = e.pageX || e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
						var y = e.pageY || e.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
						x = x + 300 > document.body.offsetWidth ? document.body.offsetWidth - 300 : x;
						y = y + 35 > document.body.offsetHeight ? document.body.offsetHeight - 35 : y;
						_me._show( x, y + 10);
					}}
				)(el);
			}
		}
	};
})();
$(document).ready(function(){
	InsDelTool.render();
});

以下是相关的CSS,对于CSS需要说明的是,这里使用了:target伪类和圆角属性,在Firefox3中可以感受一下。其中使用:target的好处在于当页面跳转到cite所指向的引用时,可以更清晰的展示目标内容。

.panel{
	border: 1px solid #bbb;
	background: #fff;
	color: #CC6600;
	font: 12px/1.5 tahomal,helvetica,sans-serif,arial;
	font-weight: bold;
	letter-spacing: 1px;
	padding: 5px;
	position: absolute;
	/*圆角,需要Firefox3*/
	-moz-border-radius: 5px; 
}
.panel a{
	color: blue;
	text-decoration: none;
}
.panel .change-type{
	font-weight:normal;
}
.panel .change-date{
	color: #669900;
}
/*CSS3 中的target伪类*/
:target{
	color: #99CC00;
	text-decoration: underline;
}