最近在做浏览器兼容。对于不兼容的方法就百度,还是比较耗时的,下面是我遇到的兼容问题总结,希望能提高你的工作效率。
一、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);
}
}
/** 获取弹出子窗口返回参数 这是ff使用的方法 */
function getRtn(rtn){
exportData(rtn);
}
/** 拆分btn_export_onclick()方法以兼容ff */
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();
}