最近在做浏覽器相容。對于不相容的方法就百度,還是比較耗時的,下面是我遇到的相容問題總結,希望能提高你的工作效率。
一、ie 支援 childNodes(i) 但 火狐隻支援 childNodes[i] 。需要批量替換,替換後火狐ie都支援。
二、ie對XMLDOM對象和DSO資料島有很好的支援,但火狐就不行了。後面遇到的相容性問題,解決辦法是:沒有對象,給它建立一個對象;沒有方法,給它添加一個方法;沒有屬性,給它增加一個屬性。能公用盡量公用。不然那麼多代碼一個一個改不現實。以下代碼都寫在公用js裡。應該能解決90%的相容性問題吧。如有疑問歡迎留言。
不支援的方法有:selectSingleNode() , selectNodes(), createElement(), attachEvent()
不支援的屬性有:documentElement, xml , text
//建立dom對象,建立後火狐沒有transformNode()方法,需要建立。
function createXMLDOM(str) {
var xmlDom;
if (!isIE()) {
// 判斷正确 建立對象
xmlDom = (new DOMParser()).parseFromString(str, 'text/xml');
// 檢測是否xml文檔有沒有問題
var error = xmlDom.getElementsByTagName("parsererror");
debugger;
if (error.length > 0) {
throw new Error("XML格式有誤:" + str);
//throw new Error("XML格式有誤:" + error[0].textContent);
}
//2020-4-16
//添加transformNode方法
xmlDom.transformNode = function(oXslDom) {
var oProcessor = new XSLTProcessor();
oProcessor.importStylesheet(oXslDom);
var oResultDom = oProcessor.transformToDocument(xmlDom);
var oSerializer = new XMLSerializer();
var sXml = oSerializer.serializeToString(oResultDom, "text/xml");
return sXml;
}
//添加xml屬性 不能在此添加xml屬性,它不是動态的,dom發生變化,但xml沒有跟着變化。具體實作參見後面
//var oSerializer = new XMLSerializer();
//xmlObj = oSerializer.serializeToString(xmlDom);
//xmlDom["xml"] = xmlObj;
//判斷是否為 IE浏覽器
}else{
var arrSignatures = new Array("MSXML.DOMDocument", "MSXML2.DOMDocument", "MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "Microsoft.XmlDom");
for (var i = 0; i < arrSignatures.length; i++) {
try {
xmlDom = new ActiveXObject(arrSignatures[i]);
if (arrSignatures[i] == "MSXML2.DOMDocument.6.0") {
xmlDom.setProperty("AllowXsltScript", "true");
}
break;
}
catch (ex) {
}
}
xmlDom.async = false;
xmlDom.loadXML(str);
var oErr = xmlDom.parseError;
if (oErr.errorCode != 0) {
alert("解析XML資料錯誤:\n" + oErr.reason + "\nLine:" + oErr.line + "\nLinepos:" + oErr.linepos + "\nsrcText:\n" + oErr.srcText);
return null;
}
}
return xmlDom;
}
<%--ff相容 判斷是否是ie浏覽器--%>
function isIE(){
if (window.navigator.userAgent.indexOf("MSIE")>=1)
return true;
else
return false;
}
<%--格式化:去掉回車換行空格 2020-5-6 此方法是主要是格式化dom的innerHTML,不格式化\t\v\s等換行符會成為dom對象的childNodes,造成取節點值報錯的情況 --%>
function formatStr(strXml){
strXml = strXml.replace(/[\n\r\t]/g, '');
strXml = strXml.replace(/>\s+</g, '><')
//将<item>abc</item> 等xml節點轉換為大寫,轉換後為<ITEM>abc</ITEM>
strXml = strXml.replace(/(<\/?)([a-z\d\:_]+)((\s+.+?)?>)/gi,function(s,a,b,c){return a+b.toUpperCase()+c;});
return strXml;
}
if(!window.ActiveXObject){
XMLDocument.prototype.selectSingleNode = Element.prototype.selectSingleNode = function (xpath){
var x = this .selectNodes(xpath)
if ( ! x || x.length < 1 ) return null ;
//去掉空格,回車,換行符
var innerH = x[0].innerHTML;
innerH = innerH.replace(/[\n\r\t]/g, '');
innerH = innerH.replace(/>\s+</g, '><');
x[0].innerHTML = innerH;
return x[ 0 ];
}
XMLDocument.prototype.selectNodes = Element.prototype.selectNodes = function (xpath){
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver( this .ownerDocument == null ?
this .documentElement : this .ownerDocument.documentElement);
var result = xpe.evaluate(xpath, this , nsResolver, 0 , null );
var found = [];
var res;
if(res = result.iterateNext()){
found.push(res);
}else{
//如果無資料則xpath變為小寫再試 wyw 2020.4.26
result = xpe.evaluate(xpath.toLowerCase(), this , nsResolver, 0 , null );
}
while (res = result.iterateNext())
found.push(res);
return found;
}
XMLDocument.prototype.createElement = Element.prototype.createElement = function (nodeName){
var node = document.createElement(nodeName);
return this.appendChild(node);
}
//相容attachEvent方法
Element.prototype.attachEvent = function(event,func){
event = event.replace('on','');
this.addEventListener(event,func,false);
}
Object.defineProperty(Element.prototype, "documentElement", {
configurable: true,
enumerable:true,
get: function (){
var docXml = formatStr(this.innerHTML);
var dso= loadXml(docXml);
return dso.documentElement;
}
});
//xmlDom 添加對象的xml屬性
Object.defineProperty(XMLDocument.prototype, "xml", {
configurable: true,
get: function (){
var oSerializer = new XMLSerializer();
var xmlObj = oSerializer.serializeToString(this);
return xmlObj;
}
});
//html元素 添加對象的xml屬性
Object.defineProperty(Element.prototype, "xml", {
configurable: true,
get: function (){
return formatStr(this.innerHTML);
}
});
Object.defineProperty(Element.prototype, "text", {
configurable: true,
get: function (){
return this.textContent;
},
set: function (val){
this.textContent = val;
}
});
}
三、另外,火狐不支援 showModalDialog。用window.open()代替。注意的是dodal=yes 這個參數設定是不起作用的。
<%--2showModalDialog是早就廢棄了的api,這裡用window.open做相容--%>
if(!window.showModalDialog){
window.showModalDialog = function(uri, args, opts){
opts = opts.replace(/:/g, '=')
.replace(/;/g, ',')
.replace('dialogWidth', 'width')
.replace('dialogHeight', 'height')
.replace('dialogheight', 'height')
.replace('dialogtop', 'top')
.replace('dialogleft', 'left')
.replace('scroll', 'scrollbars');
//讓視窗居中顯示
var iWidth = 0, iHeight = 0;
var arr = opts.split(',');
for(i=0;i<arr.length;i++){
if(arr[i].indexOf('width')>=0){
iWidth = arr[i].split('=')[1];
}
if(arr[i].indexOf('height')>=0){
iHeight = arr[i].split('=')[1];
}
}
iWidth = iWidth.replace('px', '');
iHeight = iHeight.replace('px', '');
var iTop = (window.screen.height-30-iHeight)/2; //獲得視窗的垂直位道置;
var iLeft = (window.screen.width-10-iWidth)/2; //獲得視窗的水準位置;
opts = "modal=yes,menubar=no,toolbar=no,location=no,top="+iTop+",left="+iLeft+","+opts; // 2020-5-11
var newWin = window.open(uri, '', opts);
newWin.dialogArguments = args;
return newWin;
};
}
主子視窗參數傳遞:
首頁面:
function btn_export_onclick(){
var rtn = showModalDialog("dlg_export.htm",null,"dialogWidth=500px;dialogheight=180px;status:no;help:no");
//IE可直接傳回結果。ff需要傳回結果後再執行
if(isIE()){
exportData(rtn);
}
}
function getRtn(rtn){
exportData(rtn);
}
function exportData(rtn){
if(rtn == null){
return ;
}
}
子頁面: 子頁面通過getRtn()方法傳值給首頁面,首頁面可通過該方法直接擷取值
function btn_export_onclick(){
var arr = 'abc';
//window.returnValue = arr; //2020-5-9 注釋
if(!isIE()){
window.opener.getRtn(arr);
}else{
window.returnValue = arr;
}
window.close();
}