division = (function(){ var S = KISSY, D = S.DOM, E = S.Event, ff = S.UA.firefox ? true : false, //由于火狐不支持outerHTML这里对它进行检测到时再判定,当然可以直接×.outerHTML || ×.innerHTML comment = {},//{value:[left, top, node, css, html]}value代表注释值,如start: abc,则value=abc node为comment下的第一个子节点 temp = {},//{value: true, ...} 用于判定是否存在这个注释 i = 0, zIndex = 9999; //用于设置遮盖层的层级关系 sReg = /^start:(?:/s*?)(.+?)$/, eReg = /^end:(?:/s*?)(.+?)$/; var getComment = function(arr){ var i = 0; while(arr[i]){ while(arr[i].nodeType != 1 && arr[i].nodeType != 8){ if(!arr[++i]) return; } if(arr[i].nodeType == 1){ arguments.callee(arr[i].childNodes); }else if(arr[i].nodeType == 8){ getValue(arr[i]); } i++; } } var getValue = function(node){ if(node.nodeType == 8){ if(sReg.test(node.nodeValue)){ var value = RegExp.$1; node = D.next(node); // 通过框架获取到的下一个节点时,它的nodeType一定为1 while(D.css(node, 'position') == 'absolute') node = D.next(node); if(!temp[value]){ var offset = D.offset(node); comment[value] = [offset.left, offset.top, node]; offset = null; } value = null; }else if(eReg.test(node.nodeValue)){ var value = RegExp.$1, comm; node = D.prev(node); // 通过框架获取到的下一个节点时,它的nodeType一定为1 if(comm = comment[value]){ //height = 节点的盒模式 + 注释里最下面节点的top - //最上面节点的top,不过这有一定风险,因为最后一个节点如果是绝对定位它是不占用空间的,就可能出错,所以在这里加了判断 while(D.css(node, 'position') == 'absolute') node = D.pre(node); //height为盒模式 var height = parseInt(D.css(node, 'margin-top'))+parseInt(D.css(node,'border-top-width'))+parseInt(D.css(node, 'padding-top'))+D.height(node)+parseInt(D.css(node, 'padding-bottom'))+parseInt(D.css(node,'border-bottom-width'))+parseInt(D.css(node, 'margin-bottom')), offset = D.offset(node); if(offset.left < comm[0]){ comm[0] = offset.left; } temp[value] = true; var next = comm[2], arr = [], css = { position: 'absolute', left: comm[0]+'px', top: comm[1]+'px', zIndex: zIndex--, //依次减减,因为首先获取结束注释的要么内嵌的注释要么更早的注释,当然它的层级就更高了 width: D.width(D.parent(next))+'px', //最开始是用盒模式,但后来想想这不就是它父级元素的宽吗? height: (height+offset.top-comm[1])+'px',//看上面的高度 text: value }; //comment里的css 对应comment[value][3] comm.push(css); while(next != node){ arr.push(ff ? next.innerHTML : next.outerHTML); next = D.next(next); } arr.push(ff ? next.innerHTML : next.ouerHTML); //comment里的html 对应comment[value][4] comm.push(arr.join('')); //元素置空 height = offset = next = arr = css = null; }else{ alert('注释层级有误'); return; } value = comm = null; }else{ alert('确保你注释的命名为:start: ...或者end: ...'); return; } } } //创建遮盖层 var createDivision = function(){ var arr = []; for(var value in comment){ var div = D.create('<div>',{ //'class': 'show', 'css' : comment[value][3], 'html': ['<pre style="display:none" mce_style="display:none">',comment[value][4],'</pre>'].join('') }); S.get('body').appendChild(div); E.on(div, 'mouseover mouseout', function(e){ //D.toggle(D.children(div));//显示和隐藏里面的内容 D.toggleClass(this,'show'); }); arr.push(div); div = null; } return arr; } return { init: function(arr){ //用于展现遮盖层的效果 D.addStyleSheet('.show{background-color:#000000;filter:Alpha(opacity=10);-moz-opacity:0.1;opacity:0.1;}'); getComment(arr || document.body.childNodes); this.arr = createDivision(); this.todo = true; }, hide: function(){ if(this.todo){ //do something this.arr.children.hide(); } }, show: function(){ if(this.todo){ this.arr.children().show(); } } } })(); KISSY.ready(function(){ division.init(); }); 使用这个时,注释节点需要以start:或者end: 开头才行。不过上面我写的火狐不支持,因为火狐不支持outerHTML所以用innerHTML替代,火狐浏览器下内容部完整。 具体的流程图如下:(不是很完善)