insert方法在实现火狐插入操作中,使用了W3C DOM Range对象的一些罕见方法,具体可到火狐官网查看。下面实现把字符串转换为节点,利用innerHTML这个伟大的方法。Prototype.js称之为_getContentFromAnonymousElement,但有许多问题,dojo称之为_toDom,mootools的Element.Properties.html,jQuery的clean。Ext没有这东西,它只支持传入HTML片断的insertAdjacentHTML方法,不支持传入元素节点的insertAdjacentElement。但有时,我们需要插入文本节点(并不包裹于元素节点之中),这时我们就需要用文档碎片做容器了,insert方法出场了。
复制代码 代码如下:
parseHTML : function(htmlStr, fragment){
var div = dom.doc.createElement("div"),
reSingleTag = /^<(\w+)\s*\/?>$/;//匹配单个标签,如<li>
htmlStr += '';
if(reSingleTag.test(htmlStr)){//如果str为单个标签
return [dom.doc.createElement(RegExp.$1)]
}
var tagWrap = {
option: ["select"],
optgroup: ["select"],
tbody: ["table"],
thead: ["table"],
tfoot: ["table"],
tr: ["table", "tbody"],
td: ["table", "tbody", "tr"],
th: ["table", "thead", "tr"],
legend: ["fieldset"],
caption: ["table"],
colgroup: ["table"],
col: ["table", "colgroup"],
li: ["ul"],
link:["div"]
};
for(var param in tagWrap){
var tw = tagWrap[param];
switch (param) {
case "option":tw.pre = '<select multiple="multiple">'; break;
case "link": tw.pre = 'fixbug<div>'; break;
default : tw.pre = "<" + tw.join("><") + ">";
}
tw.post = "</" + tw.reverse().join("></") + ">";
}
var reMultiTag = /<\s*([\w\:]+)/,//匹配一对标签或多个标签,如<li></li>,li
match = htmlStr.match(reMultiTag),
tag = match ? match[1].toLowerCase() : "";//解析为<li,li
if(match && tagWrap[tag]){
var wrap = tagWrap[tag];
div.innerHTML = wrap.pre + htmlStr + wrap.post;
n = wrap.length;
while(--n >= 0)//返回我们已经添加的内容
div = div.lastChild;
}else{
div.innerHTML = htmlStr;
}
//处理IE自动插入tbody,如我们使用dom.parseHTML('<thead></thead>')转换HTML片断,它应该返回
//'<thead></thead>',而IE会返回'<thead></thead><tbody></tbody>'
//亦即,在标准浏览器中return div.children.length会返回1,IE会返回2
if(dom.feature.autoInsertTbody && !!tagWrap[tag]){
var ownInsert = tagWrap[tag].join('').indexOf("tbody") !== -1,//我们插入的
tbody = div.getElementsByTagName("tbody"),
autoInsert = tbody.length > 0;//IE插入的
if(!ownInsert && autoInsert){
for(var i=0,n=tbody.length;i<n;i++){
if(!tbody[i].childNodes.length )//如果是自动插入的里面肯定没有内容
tbody[i].parentNode.removeChild( tbody[i] );
}
}
}
if (dom.feature.autoRemoveBlank && /^\s/.test(htmlStr) )
div.insertBefore( dom.doc.createTextNode(htmlStr.match(/^\s*/)[0] ), div.firstChild );
if (fragment) {
var firstChild;
while((firstChild = div.firstChild)){ // 将div上的节点转移到文档碎片上!
fragment.appendChild(firstChild);
}
return fragment;
}
return div.children;
}
嘛,基本上就是这样,运行起来比jQuery快许多,代码实现也算优美,至少没有像jQuery那样乱成一团。jQuery还有四个反转方法。下面是jQuery的实现:
复制代码 代码如下: