Reducing the number of DOMs can speed up the browser's construction of DOM Tree and render tree during the process of parsing the page, thereby improving page performance. For this purpose, we can temporarily store the part of HTML in the page that is not visible in the first screen rendering in TextArea, and then process this part of HTML after the rendering is completed to achieve this purpose. To add the HTML content temporarily stored in TextArea to the page, it is easiest and most convenient to use the outerHTML attribute of the element. However, outerHTML is not defined in the DOM standard. The supported browsers are IE6, safari, operal and Chrome. Tested in FF4.0- it is not supported yet. So let's implement a cross-browser outerHTML.
outerHTML is to get or set the html including the element tag itself. The following is the implementation code:
if(typeof HTMLElement !== "undefined" && !("outerHTML" in HTMLElement.prototype)) {
//console.log("defined outerHTML");
HTMLElement.prototype.__defineSetter__("outerHTML",function(str){
var fragment = document.createDocumentFragment();
var div = document.createElement("div");
div.innerHTML = str;
for(var i=0, n = div.childNodes .length; ifragment.appendChild(div.childNodes[i]);
}
this.parentNode.replaceChild(fragment, this);
});
//
HTMLElement.prototype.__defineGetter__("outerHTML",function(){
var tag = this.tagName;
var attributes = this.attributes;
var attr = [];
//for(var name in attributes){//Traverse the members on the prototype chain
for(var i=0,n = attributes.length; iif(attributes[i].specified){
attr.push(attributes[i].name '="' attributes[i].value '"');
}
}
return ((!!this.innerHTML) ?
'<' tag ' ' attr.join(' ') '>' this.innerHTML '' tag '>' :
'<' tag ' ' attr.join(' ') '/>');
});
}
Code description:
1 in code First, conditional judgment is made to detect whether the browser supports outerHTML to avoid overwriting the browser's native implementation.
2 "__defineSetter__", "__defineGetter__" are private aspects of firefox browser. Define the operations to be performed when setting the property value and getting the property respectively.
3 In "__defineSetter__" "outerHTML", in order to avoid inserting too many elements into the page, causing frequent reflows that affect performance. The document fragment object fragment is used to temporarily store the DOM elements that need to be inserted into the page.
4 Use the element attributes attribute in "__defineGetter__" "outerHTML" to traverse the attributes specified for the element. Combined with innerHTML returns the html string including the original attribute itself.
Test code:
outerHTML This is paragraph with a list following it p>
- Item 1
- Item 2
- Item 3
- Item 4
<script> <br>if(typeof HTMLElement !== "undefined" && !( "outerHTML" in HTMLElement.prototype)) { <br>console.log("defined outerHTML"); <br>HTMLElement.prototype.__defineSetter__("outerHTML",function(str){ <br>var fragment = document.createDocumentFragment (); <br>var div = document.createElement("div"); <br>div.innerHTML = str; <br>for(var i=0, n = div.childNodes.length; i<n; i ){ <BR>fragment.appendChild(div.childNodes[i]); <BR>} <BR>this.parentNode.replaceChild(fragment, this); <BR>}); <BR>// <BR>HTMLElement .prototype.__defineGetter__("outerHTML",function(){ <BR>var tag = this.tagName; <BR>var attributes = this.attributes; <BR>var attr = []; <BR>//for(var name in attributes){//Traverse the members on the prototype chain<BR>for(var i=0,n = attributes.length; i<n; i){//The number of attributes specified by n<BR>if(attributes[ i].specified){ <BR>attr.push(attributes[i].name '="' attributes[i].value '"'); <BR>} <BR>} <BR>return ((!! this.innerHTML) ? <BR>'<' tag ' ' attr.join(' ') '>' this.innerHTML '</' tag '>' : <br>'<' tag ' ' attr.join(' ') '/>'); <br>}); <br>} <br>var content = document.getElementById("content"); <br>alert(content.outerHTML) <br></script>
Suppose you want to get the outerHTML
code of P of
sdfdsdfsd
:
var _p = document.getElementById('outerID');
_P = _P.cloneNode();
var _DIV = document.createElement ();
_DIV.appendChild(_P);
alert(_DIV.innerHTML); is P’s outerHTML;
firefox does not have outerHTML, use the following method to solve it
/**
* Firefox compatible outerHTML After using the following code, firefox can use element.outerHTML
**/
if(window.HTMLElement) {
HTMLElement.prototype.__defineSetter__("outerHTML",function(sHTML){
var r=this.ownerDocument.createRange();
r.setStartBefore(this);
var df=r. createContextualFragment(sHTML);
this.parentNode.replaceChild(df,this);
return sHTML;
});
HTMLElement.prototype.__defineGetter__("outerHTML",function(){
var attr;
var attrs=this.attributes;
var str="<" this.tagName.toLowerCase();
for(var i=0;i
attr=attrs[i];
if(attr.specified)
str =" " attr.name '="' attr.value '"';
}
if( !this.canHaveChildren)
return str ">";
return str ">" this.innerHTML "" this.tagName.toLowerCase() ">";
});
HTMLElement.prototype.__defineGetter__("canHaveChildren",function(){
switch(this.tagName.toLowerCase()){
case "area":
case "base":
case "basefont":
case "col":
case "frame":
case "hr":
case "img":
case "br":
case " input":
case "isindex":
case "link":
case "meta":
case "param":
return false;
}
return true ;
});
}
The test is valid.
About the new solution for insertAdjacentHTML compatibility
//---Insert html code at the end of the component
function InsertHtm(op,code,isStart){
if (Dvbbs_IsIE5)
op.insertAdjacentHTML(isStart ? "afterbegin" : "afterEnd",code);
else{
var range=op.ownerDocument.createRange();
range.setStartBefore(op );
var fragment = range.createContextualFragment(code);
if(isStart)
op.insertBefore(fragment,op.firstChild);
else
op.appendChild(fragment);
}
}
关于inner/outerHTML在NC6中的参考
DOM level 1 has no methods to allow for insertion of unparsed HTML into the document tree (as IE allows with insertAdjacentHTML or assignment to inner/outerHTML).NN6 (currently in beta as NN6PR3) know supports the .innerHTMLproperty of HTMLElements so that you can read or write the innerHTML of a page element like in IE4+.NN6 also provides a DOM level 2 compliant Range object to which a createContextualFragment('html source string')was added to spare DOM scripters the task of parsing html and creating DOM elements.You create a Range with var range = document.createRange();Then you should set its start point to the element where you want to insert the html for instance var someElement = document.getElementById('elementID'); range.setStartAfter(someElement);Then you create a document fragment from the html source to insert for example var docFrag = range.createContextualFragment('
Kibology for all.
');and insert it with DOM methods someElement.appendChild(docFrag);The Netscape JavaScript 1.5 version even provides so called setters for properties which together with the ability to prototype the DOM elements allows to emulate setting of outerHMTL for NN6: If you insert that script block you can then write cross browser code assigning to .innerHTML .outerHTMLfor instance document.body.innerHTML = '
Scriptology for all
';which works with both IE4/5 and NN6.The following provides getter functions for .outerHTMLto allow to read those properties in NN6 in a IE4/5 compatible way. Note that while the scheme of traversing the document tree should point you in the right direction the code example might not satisfy your needs as there are subtle difficulties when trying to reproduce the html source from the document tree. See for yourself whether you like the result and improve it as needed to cover other exceptions than those handled (for the empty elements and the textarea element).
show document.documentElement.outerHTML|
show document.body.outerHTML|
show document.documentElement.innerHTML|
show document.body.innerHTMLJavaScript.FAQTs.com
Kibology for all.
All for Kibology.
getter/setter 기능은 실험적이며 해당 구문은 변경될 수 있습니다.
HTMLElement.prototype.innerHTML setter = function (str) { var r = this.ownerDocument.createRange(); r.selectNodeContents(this); r.deleteContents(); var df = r.createContextualFragment(str); this.appendChild(df); return str;}HTMLElement.prototype.outerHTML setter = function (str) { var r = this.ownerDocument.createRange(); r.setStartBefore(this); var df = r.createContextualFragment(str); this.parentNode.replaceChild(df, this); return str;}
HTMLElement.prototype.innerHTML getter = function () { return getInnerHTML(this);}
function getInnerHTML(node) { var str = ""; for (var i=0; i
HTMLElement.prototype.outerHTML getter = function () { return getOuterHTML(this)}
function getOuterHTML(node) { var str = ""; 스위치 (node.nodeType) { 사례 1: // ELEMENT_NODE str = "<" 노드.노드이름; for (var i=0; iif (node.childNodes.length == 0 && leafElems[node.nodeName]) str = ">"; else { str = ">"; str = getInnerHTML(노드); str = "<" node.nodeName ">" } 부서지다; 사례 3: //TEXT_NODE str = node.nodeValue; 부서지다; 사례 4: // CDATA_SECTION_NODE str = ""; 부서지다; 사례 5: // ENTITY_REFERENCE_NODE str = "&" node.nodeName ";" 부서지다;
사례 8: // COMMENT_NODE str = "" 부서지다; }
문자열 반환}
var _leafElems = ["IMG", "HR", "BR", "INPUT"];var leafElems = {};for (var i=0; i<_leafElems.length ; i ) leafElems[_leafElems[i]] = true; <… >');