天天看點

IE與FF javascript相容的寫法

一、函數和方法差異

1 . getYear()方法

【分析說明】先看一下以下代碼:

var

year

=

new

Date().getYear();

document.write(year);

  在IE中得到的日期是"2010",在Firefox中看到的日期是"110",主要是因為在 Firefox 裡面 getYear 傳回的是 "目前年份-1900" 的值。

【相容處理】

  加上對年份的判斷,如:

var

year

=

new

Date().getYear();

year

=

(year

<

1900

?

(

1900

+

year):year);

document.write(year);

  也可以通過 getFullYear getUTCFullYear 去調用:

var

year

=

new

Date().getFullYear();

document.write(year);

2 . eval()函數

【分析說明】在IE中,可以使用eval("idName")或getElementById("idName")來取得id為idName的 HTML對象;Firefox下隻能使用getElementById("idName")來取得id為idName的HTML對象。

【相容處理】統一用getElementById("idName")來取得id為idName的HTML對象。

3 . const聲明

【分析說明】在 IE 中不能使用 const 關鍵字。如:

const constVar

=

32

;

在IE中這是文法錯誤。

【相容處理】不使用 const ,以 var 代替。

4 . var

【分析說明】請看以下代碼:

echo

=

function

(str){

document.write(str);

}

  這個函數在IE上運作正常,Firefox下卻報錯了。

【相容處理】而在echo前加上var就正常了,這個就是我們提到var的目的。

5 . const 問題

【分析說明】在 IE 中不能使用 const 關鍵字。如 const constVar = 32; 在IE中這是文法錯誤。

【解決方法】不使用 const ,以 var 代替。

二、樣式通路和設定

1 . CSS的"float"屬性

【分析說明】Javascript通路一個給定CSS 值的最基本句法是:object.style.property,但部分CSS屬性跟Javascript中的保留字命名相同,如"float","for","class"等,不同浏覽器寫法不同。

在IE中這樣寫:

document.getElementById(

"

header

"

).style.styleFloat

=

"

left

"

;

在Firefox中這樣寫:

document.getElementById(

"

header

"

).style.cssFloat

=

"

left

"

;

【相容處理】在寫之前加一個判斷,判斷浏覽器是否是IE:

if

(document.all){

  document.getElementById(

"

header

"

).style.styleFloat

=

"

left

"

;

}

else

{

  document.getElementById(

"

header

"

).style.cssFloat

=

"

left

"

;

}

2 . 通路<label>标簽中的"for"

【分析說明】和"float"屬性一樣,同樣需要使用不現的句法區分來通路<label>标簽中的"for"。

在IE中這樣寫:

var

myObject

=

document.getElementById(

"

myLabel

"

);

var

myAttribute

=

myObject.getAttribute(

"

htmlFor

"

);

在Firefox中這樣寫:

var

myObject

=

document.getElementById(

"

myLabel

"

);

var

myAttribute

=

myObject.getAttribute(

"

for

"

);

【相容處理】解決的方法也是先 判斷浏覽器類型。

3 . 通路和設定class屬性

【分析說明】同樣由于class是Javascript保留字的原因,這兩種浏覽器使用不同的 JavaScript 方法來擷取這個屬性。

IE8.0之前的所有IE版本的寫法:

var

myObject

=

document.getElementById(

"

header

"

);

var

myAttribute

=

myObject.getAttribute(

"

className

"

);

适用于IE8.0 以及 firefox的寫法:

var

myObject

=

document.getElementById(

"

header

"

);

var

myAttribute

=

myObject.getAttribute(

"

class

"

);

  另外,在使用setAttribute()設定Class屬性的時候,兩種浏覽器也存在同樣的差異。

  setAttribute("className",value);

  這種寫法适用于IE8.0之前的所有IE版本,注意:IE8.0也不支援"className"屬性了。

  setAttribute("class",value);适用于IE8.0 以及 firefox。

【相容處理】

方法一,兩種都寫上:

var

myObject

=

document.getElementById(

"

header

"

);

myObject.setAttribute(

"

class

"

,

"

classValue

"

);

myObject.setAttribute(

"

className

"

,

"

classValue

"

);

//

設定header的class為classValue

方法二,IE和FF都支援object.className,是以可以這樣寫:

var

myObject

=

document.getElementById(

"

header

"

);

myObject.className

=

"

classValue

"

;

//

設定header的class為classValue

方法三,先判斷浏覽器類型,再根據浏覽器類型采用對應的寫法。

4 . 對象寬高指派問題

【分析說明】FireFox中類似 obj.style.height = imgObj.height 的語句無效。

【相容處理】統一使用 obj.style.height = imgObj.height + ‘px’;

三、DOM方法及對象引用

1 . getElementById

【分析說明】先來看一組代碼:

<!--

input對象通路1

-->

<

input

id

="id"

type

="button"

value

="click me"

ōnclick

="alert(id.value)"/

>

  在Firefox中,按鈕沒反應,在IE中,就可以,因為對于IE來說,一個HTML 元素的 ID 可以直接在腳本中當作變量名來使用,而Firefox中不可以。

【相容處理】盡量采用W3C DOM 的寫法,通路對象的時候,用document.getElementById("id") 以ID來通路對象,且一個ID在頁面中必須是唯一的,同樣在以标簽名來通路對象的時候,用document.getElementsByTagName("div") [0] 。該方式得到較多浏覽器的支援。

<!--

input對象通路2

-->

<

input

id

="id"

type

="button"

value

="click me"

onclick

="alert(document.getElementById('id').value)" /

>

2 . 集合類對象通路

【分析說明】IE下,可以使用()或[]擷取集合類對象;Firefox下,隻能使用[]擷取集合類對象。如:

document.write(document.forms(

"

formName

"

).src);

//該寫法在IE下能通路到Form對象的scrc屬性

【相容處理】将document.forms("formName")改為 document.forms["formName"]。統一使用[]擷取集合類對象。

3 . frame的引用

【分析說明】IE可以通過id或者name通路這個frame對應的window對象,而Firefox隻可以通過name來通路這個frame對應的window對象。

  例如如果上述frame标簽寫在最上層的window裡面的htm裡面,那麼可以這樣通路:

IE: window.top.frameId或者window.top.frameName來通路這個window對象;

Firefox:隻能這樣window.top.frameName來通路這個window對象。

【相容處理】使用frame的name來通路frame對象,另外,在IE和Firefox中都可以使用window.document.getElementById(”frameId”)來通路這個frame對象。

4 . parentElement

【分析說明】IE中支援使用parentElement和parentNode擷取父節點。而Firefox隻可以使用parentNode。

【相容處理】因為firefox與IE都支援DOM,是以統一使用parentNode來通路父節點。

5 . table操作

【分析說明】IE下table中無論是用innerHTML還是appendChild插入<tr>都沒有效果,而其他浏覽器卻顯示正常。

【相容處理】解決的方法是,将<tr>加到table的<tbody>元素中,如下面所示:

var

row

=

document.createElement(

"

tr

"

);

var

cell

=

document.createElement(

"

td

"

);

var

cell_text

=

document.createTextNode(

"

插入的内容

"

);

cell.appendChild(cell_text);

row.appendChild(cell);

document.getElementsByTagName(

"

tbody

"

)[

].appendChild(row);

6 . 移除節點removeNode()和removeChild()

【分析說明】appendNode在IE和Firefox下都能正常使用,但是removeNode隻能在IE下用。

  removeNode方法的功能是删除一個節點,文法為node.removeNode(false)或者node.removeNode(true),傳回值是被删除的節點。

  removeNode(false)表示僅僅删除指定節點,然後這個節點的原孩子節點提升為原雙親節點的孩子節點。

  removeNode(true)表示删除指定節點及其所有下屬節點。被删除的節點成為了孤立節點,不再具有有孩子節點和雙親節點。

【相容處理】Firefox中節點沒有removeNode方法,隻能用removeChild方法代替,先回到父節點,在從父節點上移除要移除的節點。

node.parentNode.removeChild(node);

//

為了在ie和firefox下都能正常使用,取上一層的父結點,然後remove。

7 . childNodes擷取的節點

【分析說明】childNodes的下标的含義在IE和Firefox中不同,看一下下面的代碼:

<

ul

id

="main"

>

<

li

>

1

</

li

>

<

li

>

2

</

li

>

<

li

>

3

</

li

>

</

ul

>

<

input

type

=button

value

="click me!"

onclick

=

"alert(document.getElementById('main').childNodes.length)"

>

分别用IE和Firefox運作,IE的結果是3,而Firefox則是7。Firefox使用DOM規範,"#text"表示文本(實際是無意義的空格和換行等)在Firefox裡也會被解析成一個節點,在IE裡隻有有實際意義的文本才會解析成"#text"。

【相容處理】

方法一,擷取子節點時,可以通過node.getElementsByTagName()來回避這個問題。但是 getElementsByTagName對複雜的DOM結構周遊明顯不如用childNodes,因為childNodes能更好的處理DOM的層次結構。

方法二,在實際運用中,Firefox在周遊子節點時,不妨在for循環裡加上:

if

(childNode.nodeName

=="

#text

"

)

continue

;

//

或者使用nodeType == 1。

這樣可以跳過一些文本節點。

延伸閱讀

  《IE和FireFox中的childNodes差別 》

8 . Firefox不能對innerText支援

【分析說明】Firefox不支援innerText,它支援textContent來實作innerText,不過textContent沒有像 innerText一樣考慮元素的display方式,是以不完全與IE相容。如果不用textContent,字元串裡面不包含HTML代碼也可以用 innerHTML代替。也可以用js寫個方法實作,可參考《為firefox實作innerText屬性 》一文。

【相容處理】通過判斷浏覽器類型來相容:

if

(document.all){

document.getElementById(

'

element

'

).innerText

=

"

my text

"

;

}

else

{

document.getElementById(

'

element

'

).textContent

=

"

my text

"

;

}

四、事件處理

  如果在使用javascript的時候涉及到event處理,就需要知道event在不同的浏覽器中的差異,主要的JavaScript的事件模型有三種(參考《Supporting Three Event Models at Once 》),它們分别是NN4、IE4+和W3C/Safar。

1 . window.event

【分析說明】先看一段代碼

function

et()

{

    alert(event);

//

IE: [object]

}

  以上代碼在IE運作的結果是[object],而在Firefox無法運作。

  因為在IE中event作為window對象的一個屬性可以直接使用,但是在Firefox中卻使用了W3C的模型,它是通過傳參的方法來傳播事件的,也就是說你需要為你的函數提供一個事件響應的接口。

【相容處理】添加對event判斷,根據浏覽器的不同來得到正确的event:

function

et()

{

    evt

=

evt

?

evt:(window.event

?

window.event:

null

);

  

//

相容IE和Firefox

    alert(evt);

}

2 . 鍵盤值的取得

【分析說明】IE和Firefox擷取鍵盤值的方法不同,可以了解,Firefox下的event.which與IE下的event.keyCode相當。關于彼此不同,可參考《鍵盤事件中keyCode、which和charCode 的相容性測試 》

【相容處理】

function

myKeyPress(evt){

    //相容IE和Firefox獲得keyBoardEvent對象

    evt

=

(evt)

?

evt : ((window.event)

?

window.event :

""

)

//

相容IE和Firefox獲得keyBoardEvent對象的鍵值

var

key

=

evt.keyCode

?

evt.keyCode:evt.which;

if

(evt.ctrlKey

&&

(key

==

13

||

key

==

10

)){

      //

同時按下了Ctrl和Enter鍵

//

do something;

    }

}

3 . 事件源的擷取

【分析說明】在使用事件委托的時候,通過事件源擷取來判斷事件到底來自哪個元素,但是,在IE下,event對象有srcElement屬性,但是沒有target屬性;Firefox下,even對象有target屬性,但是沒有srcElement屬性。

【相容處理】

ele

=

function

(evt){

//

捕獲目前事件作用的對象

   evt

=

evt

||

window.event;

  return

  (obj=event.srcElement?event.srcElement:event.target;

);

}

4 . 事件監聽

【分析說明】在事件監聽處理方面,IE提供了attachEvent和detachEvent兩個接口,而Firefox提供的是addEventListener和removeEventListener。

【相容處理】最簡單的相容性處理就是封裝這兩套接口:

function

addEvent(elem, eventName, handler) {

  

if

(elem.attachEvent) {

    elem.attachEvent(

"

on

"

+

eventName,

function

(){

                    handler.call(elem)});

    //此處

使用回調函數call(),讓this指向elem

  }

else

if

(elem.addEventListener) {

    elem.addEventListener(eventName, handler,

false

);

  }

}

function

removeEvent(elem, eventName, handler) {

  

if

(elem.detachEvent) {

    elem.detachEvent(

"

on

"

+

eventName,

function

(){

                    handler.call(elem)});

    //此處

使用回調函數call(),讓this指向elem

  }

else

if

(elem.removeEventListener) {

    elem.removeEventListener(eventName, handler,

false

);

  }

}

  需要特别注意,Firefox下,事件處理函數中的this指向被監聽元素本身,而在IE下則不然,可使用回調函數call,讓目前上下文指向監聽的元素。

5 . 滑鼠位置

【分析說明】IE下,even對象有x,y屬性,但是沒有pageX,pageY屬性;Firefox下,even對象有pageX,pageY屬性,但是沒有x,y屬性。

【相容處理】使用mX(mX = event.x ? event.x : event.pageX;)來代替IE下的event.x或者Firefox下的event.pageX。複雜點還要考慮絕對位置。

function

getAbsPoint(e){

var

x

=

e.offsetLeft, y

=

e.offsetTop;

while

(e

=

e.offsetParent) {

        x

+=

e.offsetLeft;

        y

+=

e.offsetTop;

    }

    alert(

"

x:

"

+

x

+

"

,

"

+

"

y:

"

+

y);

}

五、其他差異的相容處理

1 . XMLHttpRequest

【分析說明】new ActiveXObject("Microsoft.XMLHTTP");隻在IE中起作用,Firefox不支援,但支援XMLHttpRequest。

【相容處理】

function

createXHR() {

var

xhr

=

null

;

if

(window.XMLHttpRequest){

        xhr

=

new

ActiveXObject(

"

Msxml2.XMLHTTP

"

);

    }

else

{

try

{

            xhr

=

new

ActiveXObject(

"

Microsoft.XMLHTTP

"

);

        }

catch

() {

            xhr

=

null

;

        }

    }

if

(

!

xhr)

return

;

return

xhr;

}

2 . 模态和非模态視窗

【分析說明】IE中可以通過showModalDialog和showModelessDialog打開模态和非模态視窗,但是Firefox不支援。

【解決辦法】直接使用window.open(pageURL,name,parameters)方式打開新視窗。 如果需要傳遞參數,可以使用frame或者iframe。

3. input.type屬性問題

IE下 input.type屬性為隻讀,但是Firefox下可以修改

4 . 對select元素的option操作

設定options,IE和Firefox寫法不同:

Firefox:可直接設定

option.text

=

'

foooooooo

'

;

IE:隻能設定

option.innerHTML

=

'

fooooooo

'

;

删除一個select的option的方法:

Firefox:可以

select.options.remove(selectedIndex);

IE7:可以用

select.options[i]

=

null

;

IE6:需要寫

select.options[i].outerHTML

=

null

;

5 . img對象alt和title的解析

【分析說明】img對象有alt和title兩個屬性,差別在于,alt:當照片不存在或者load錯誤時的提示。

title:照片的tip說明, 在IE中如果沒有定義title,alt也可以作為img的tip使用,但是在Firefox中,兩者完全按照标準中的定義使用

在定義img對象時。

【相容處理】最好将alt和title對象都寫全,保證在各種浏覽器中都能正常使用 。

6 . img的src重新整理問題

【分析說明】先看一下代碼:

<

img

id

="pic"

onclick

= "this.src= 'a.jpg'"

   src

="aa.jpg"

style

="cursor: pointer"

/>

在IE 下,這段代碼可以用來重新整理圖檔,但在FireFox下不行。主要是緩存問題。

【相容處理】在位址後面加個随機數就解決了:

<

img

id

="pic"

onclick

= "javascript:this.src=this.src+'?'

     +Math.random()"src

="a.jpg"

style

="cursor: pointer"

/>

1. 對象問題 1.1 Form對象

現有問題:現有代碼這獲得form對象通過document.forms("formName"),這樣使用在IE 能接受,MF 不能。解決方法:改用 作為下标運算。改為document.forms["formName"] 備注上述的改用 作為下标運算中的formName是id而name

1.2 HTML對象 現有問題:在 IE 中,HTML 對象的 ID 可以作為 document 的下屬對象變量名直接使用。在 MF 中不能。 document.all("itemName")或者document.all("itemId") 解決方法:使用對象ID作為對象變量名 document.getElementById("itemId") 備注 document.all是IE自定義的方法,是以請大家盡量不使用。還有一種方式,在IE和MF都可以使用 var f = document.forms["formName "]; var o = f. itemId;

1.3 DIV對象

現有問題:在 IE 中,DIV對象可以使用ID作為對象變量名直接使用。在 MF 中不能。 DivId.style.display = "none" 解決方法: document.getElementById("DivId").style.display = "none" 備注獲得對象的方法不管是不是DIV對象,都使用getElementById方法。參見1.2

1.4 關于frame 現有問題在 IE中 可以用window.testFrame取得該frame,mf中不行解決方法在frame的使用方面MF和IE的最主要的差別是:如果在frame标簽中書寫了以下屬性:

那麼IE可以通過id或者name通路這個frame對應的window對象而mf隻可以通過name來通路這個frame對應的window對象例如如果上述frame标簽寫在最上層的window裡面的htm裡面,那麼可以這樣通路 IE: window.top.frameId或者window.top.frameName來通路這個window對象 MF:隻能這樣window.top.frameName來通路這個window對象另外,在mf和ie中都可以使用window.top.document.getElementById("frameId")來通路frame标簽并且可以通過window.top.document.getElementById("testFrame").src = 'xx.htm'來切換frame的内容也都可以通過window.top.frameName.location = 'xx.htm'來切換frame的内容

1.5 視窗

現有問題 IE中可以通過showModalDialog和showModelessDialog打開模态和非模态視窗,但是MF不支援。解決辦法直接使用window.open(pageURL,name,parameters)方式打開新視窗。如果需要傳遞參數,可以使用frame或者iframe。

2. 總結 2.1 在JS中定義各種對象變量名時,盡量使用id,避免使用name。 在 IE 中,HTML 對象的 ID 可以作為 document 的下屬對象變量名直接使用。在 MF 中不能,是以在平常使用時請盡量使用id,避免隻使用name,而不使用id。

2.2 變量名與某 HTML 對象 id 相同的問題 現有問題在 MF 中,因為對象 id 不作為 HTML 對象的名稱,是以可以使用與 HTML 對象 id 相同的變量名,IE 中不能。解決方法在聲明變量時,一律加上 var ,以避免歧義,這樣在 IE 中亦可正常運作。此外,最好不要取與 HTML 對象 id 相同的變量名,以減少錯誤。

1. document.all Firefox可以相容document.all, 但會生成一條警告。可以用getElementById("*") 或者 getElementByTagName("*)來代替不過對于document.all.length等屬性,則完全不相容。 2. parentElement 這個也不相容。比方說, obj.parentElement.name 則應改成

view plaincopy to clipboardprint?

obj.parentNode.attributes.getNamedItem("name").nodeValue  

 obj.parentNode.attributes.getNamedItem("name").nodeValue (不知道如何寫得更簡潔些) 3. event W3C不支援windows.event 比方說: 在IE裡面 

判斷浏覽器navigator.appName == "Microsoft Internet Explorer" navigator.userAgent.indexOf("MSIE")>0 firefox不支援 window.close() innerText textContent firefox隻有在window.open()的情況下支援window.close();但如果這個頁是iframe也不行,建議用top.close. children不支援,支援childNodes firefox讀xml也要注意IE裡面01234子節點,firefox裡面就變成13579了

 IE

view plaincopy to clipboardprint?

var opname=c.childNodes[0].text;  

var opid=c.childNodes[1].text;  

var opurl=c.childNodes[2].text;  

var opuser=c.childNodes[3].text;  

var opadress=c.childNodes[4].text 

var opname=c.childNodes[0].text;

var opid=c.childNodes[1].text;

var opurl=c.childNodes[2].text;

var opuser=c.childNodes[3].text;

var opadress=c.childNodes[4].textFF

view plaincopy to clipboardprint?

var opname=c.childNodes[1].textContent;  

var opid=c.childNodes[3].textContent;  

var opurl=c.childNodes[5].textContent;  

var opuser=c.childNodes[7].textContent;  

var opadress=c.childNodes[9].textContent; 

var opname=c.childNodes[1].textContent;

var opid=c.childNodes[3].textContent;

var opurl=c.childNodes[5].textContent;

var opuser=c.childNodes[7].textContent;

var opadress=c.childNodes[9].textContent;但是firefox還是支援chindNodes的

在firefox中,自己定義的屬性必須getAttribute()取得但是千萬注意,getAttribute()取得的值是不會變的,比如 var a=b.getAttribute("屬性") b.屬性=100 var c=b.getAttribute("屬性") 不管b.屬性改成多少,a和c是相等的。建議操作方式全局變量 fag=0; if(fag==0) fag=b.屬性=b.getAttribute("屬性");

firefox不能寫function a.b()    {} 要寫成a.b=function(){}

firefox不支援src="file:///c:a.gif";

xmlHttp.setRequestHeader firefox裡面一定要大寫

ff的ajax,IE裡面可以有很多寫法,但ff裡面有時就會出錯,下面寫一種不會出錯的寫法

view plaincopy to clipboardprint?

function GetDataFromServer( url, id )  

{  

    if(window.XMLHttpRequest)  

    { request = new XMLHttpRequest();}  

    else   

    if(window.ActiveXObject)  

    { request = new ActiveXObject("MSXML2.XMLHTTP.5.0");}  

    var serverUrl = url ;  

    if( request )  

    {  

     window.status = "資料更新中...." ;  

     request.open("get",serverUrl,true) ;  

     request.setRequestHeader("content-type","application/x-www-form-  

urlencoded") ;  

     request.onreadystatechange = function(){onResponse(id);};  

     request.send(null) ;  

    }  

}  

   function onResponse(id)  

   {  

    var xmlHttp=request;  

    if(xmlHttp.readyState == 4)  

    {  

     if(xmlHttp.status == 200)  

     {             

      var result = xmlHttp.responseText ;  

      if(document.getElementById("load_"+id))  

      {  

       邏輯;  

      }  

      window.status = "資料更新完成" ;  

     }  

    }  

   } 

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/tkjune/archive/2008/07/02/2606699.aspx

轉載于:https://www.cnblogs.com/zhaoyx/articles/1708098.html

繼續閱讀