1)問題描述:
在Android內建瀏覽器中,如果出現跨文檔的節點操作時(這裡的操作指剪下節點),拋異常——WRONG_DOCUMENT_ERR: DOM Exception 4
例如對一個元素進行inserBefore、appendChild操作,其參數子節點來自其他文檔。
2)測試如下:
crossdom.html頁面中引入了一個同源的test.html,當點擊按鈕時,會將test.html中的div1從test.html中剪下到當前頁面crossdom.html中
2-1)crossdom.html中如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html;charset=gbk"> <TITLE> 跨文檔appendChild操作 </TITLE> <script type="text/javascript"> function crossDom(){ var ifr = document.getElementById('ifr'); var doc = document.all ? ifr.Document : ifr.contentDocument; document.body.appendChild(doc.getElementById('div1')); } </script> </HEAD> <BODY> <fieldset style='float:left;border:solid #000 2px;padding:5px;'> <legend>test page 中的內容:</legend> <iframe id='ifr' src='test.html'></iframe> </fieldset> <button style='margin-top:200px' onclick='crossDom()'>將test page中你的div剪下到本文檔中</button> </BODY></HTML>
2-2)test.html中內容如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html;charset=gbk"> <TITLE> test page </TITLE> </HEAD> <BODY> <div id="div1" style="width:100px;height:100px;background-color:green;">test page </div> </BODY></HTML>
3)測試結果:
3-1)pc端:包括ie6+、chrome和firefox最新更新版本等,均沒有拋錯,能正常實現跨文檔剪下。
3-2)移動端:Android內建瀏覽器中,2.3及其以下版本進行測試。無法剪下,拋異常——WRONG_DOCUMENT_ERR: DOM Exception 4
W3C DomException中已經定義了WRONG_DOCUMENT_ERR的含義,並且描述了跨文檔節點操作會拋此異常,可參照下此處關於WRONG_DOCUMENT_ERR的定義:http://reference.sitepoint.com/javascript/DOMException
但是經過一輪測試發現,除了android內建瀏覽器遵循此規範,拋此錯誤,其它的均不會,包括Android下的第三方瀏覽器uc8.7竟然也沒錯(其它一些雜七雜八的android第三方瀏覽器沒有測試)。
4)實現Android內建瀏覽器下的跨文檔的節點操作:
其實就是在剪下前,對節點進行複製。
可通過document.importNode(http://reference.sitepoint.com/javascript/Document/importNode,ie不支援importNode)或者cloneNode介面,複製節點後再進行appendChild操作即可。
例如將crossdom.html改成如下即可:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html;charset=gbk"> <TITLE> 跨文檔appendChild操作 </TITLE> <script type="text/javascript"> function crossDom(){ var ifr = document.getElementById('ifr'); var doc = document.all ? ifr.Document : ifr.contentDocument;
var div1 = doc.getElementById('div1');
document.body.appendChild(div1.cloneNode());
//或者如下:
//document.body.appendChild(docuemnt.importNode(doc.getElementById('div1')));
div1.parentNode.removeChild(div1);
} </script> </HEAD> <BODY> <fieldset style='float:left;border:solid #000 2px;padding:5px;'> <legend>test page 中的內容:</legend> <iframe id='ifr' src='test.html'></iframe> </fieldset> <button style='margin-top:200px' onclick='crossDom()'>將test page中你的div剪下到本文檔中</button> </BODY></HTML>
ps:
個人猜測Android內建瀏覽器在理解W3C DomException中的WRONG_DOCUMENT_ERR也許有偏差。因為跨文檔剪下看似阻止了文檔間dom直接操作,但是僅僅通過一個複製就突破了。而且只要dom文檔間能訪問,就可通過innerHTML等字串操作,變相實現節點的剪下。