檢測瀏覽器對事件不同的處理方式

目前西方很多WEB開發工作者對瀏覽器的研究幾乎達到一個狂熱的程度,這歸根到底還是源於jQuery搞出特性偵探這個屬性。但是由於瀏覽器內核的不同,導致不同的瀏覽器對事件的處理方式是有區別的,比如在IE瀏覽器下是支持mouseenter與mouseleave,Opera支持右鍵菜單但不允許你用contextmenu類似的API操作它,還有onbeforepaste, onbeforecut這些與input元素相關的事件,IE瀏覽器與WebKit支持,但FF不支持。當然還有一些像「阻止事件冒泡」以及「取消瀏覽器默認行為」等,不同瀏覽器也有不同的處理方式,如果我們要使JavaScript在不同的瀏覽器下能正常處理事件代碼,就要分別進行判斷處理。而jQuery類庫為我們提供了屏蔽瀏覽器的差異的辦法。

jQuery是一種讓開發和設計者在他們的網頁中添加交互內容的工具,它的核心命令讓你在網頁中定位或創建對象並對之進行操作,它事實上是一種更容易使用的JavaScript,可以不必強迫頁面刷新而對頁面進行各種操作。

JavaScript為設計拓寬了視野,而jQuery讓這一切變得更簡單。對那些通曉CSS的設計師來說,編寫jQuery代碼很類似,而對於那些擁有Flash經驗的設計師來說,jQuery是一種標準化的,開放的技術,它可以實現類似Flash的交互效果,讓網頁能夠在瀏覽器中呈現更加多樣化的效果。

在以前javascript與DOM遍地是bug,美工主宰前端的年代,人們只有兩種極端方式,用戶禁止腳本運行,瀏覽器商狂升級(IE6之前也很積極的)。這年頭,也就Base2與Prototype2做得最好,當然dojo與YUI也不錯。不過最近五年,Opera與Safari都建立了對DOM完整的支持後,世界分兩半,一半是IE瀏覽器統治的混亂世界,它是擁有如此豐富的私有特徵,CSS表達式,HTC,CSS濾鏡,VML,userData,XML數據島,最早的AJAX支持,以及DHTML最好的支持API(innerHTML,innerText,outerHTML,outerText,insertAdjactentXXX,offsetXXX,clientXXX,scrollXXX,Range,designMode,sertRow和insertCell等動態操作表格API……),難怪IE會贏的!不過IE也埋下了許多地雷,加之IE瀏覽器不會像其他遊覽器升級那麼快,許多Bug都要我們親手修正。這麼多瀏覽器,這麼多版本,特性偵探是很有必要。現在我們看到那一套關於事件的API,基本上是微軟從桌面搬過來,後來W3C又加一大堆與DOM開頭的事件,不過除了DOMMouseScroll基本沒什麼人用。N多事件,與逐個嗅探瀏覽器那樣成了個頭痛的問題。

一般我們可以用for…in循環把它遍歷一下,或者像以下簡單地檢測:

『onclick』 in document.documentElement; // true『onclick2′ in document.documentElement; // false很不幸,這不準確,因為我們可以添加一些同名的自定義屬性。有人說,趕在用戶添加之前檢測它們,但也行不通,因此有些事件是只有特定元素才有的。

『onreset』 in document.documentElement; // false『onreset』 in document.createElement(』input』); // true在標準瀏覽器我們可以用setAttrubute為元素賦以已知事件名一個值,這個值會自動包裝成一個函數,如果非事件名,則不會改變其類型。那麼我檢測它是否為函數就是!

var el = document.createElement(』div』);

el.setAttribute(』onclick』, 『return;』);alert(typeof el.onclick); // 「function」

el.setAttribute(』onclick2′, 『return;』);alert(typeof el.onclick2); // 「undefined」同樣很不幸,基於眾所周知的原因,IE的setAttribute與W3C是有很大的差別,IE會原樣輸出,加之,IE不存在所謂的泛化函數(原生對象的方法),它的API沒有name,call,apply與toString,因此也無法判定它們是否為函數。綜合以上兩種方式,看看外國人搞出什麼怪物來……

var isEventSupported = (function(){//使用模塊模式

var TAGNAMES = {//特定元素上的特定事件』select』:"input』,"change』:"input』,』submit』:"form』,"reset』:"form』,『error』:"img』,"load』:"img』,"abort』:"img』}

function isEventSupported(eventName, element) {

element = element || document.createElement(TAGNAMES[eventName] || 『div』);eventName = 『on』 + eventName;

// When using `setAttribute`, IE skips 「unload」, WebKit skips 「unload」 and 「resize」, whereas `in` 「catches」 thosevar isSupported = (eventName in element);//DOM0

if (!isSupported) {// if it has no `setAttribute` (i.e. doesn』t implement Node interface), try generic elementif (!element.setAttribute) {element = document.createElement(』div』);}if (element.setAttribute && element.removeAttribute) {element.setAttribute(eventName, 」);isSupported = typeof element[eventName] == 『function』;

// if property was created, 「remove it」 (by setting value to `undefined`)if (typeof element[eventName] != 『undefined』) {element[eventName] = void 0;}element.removeAttribute(eventName);}}

element = null;return isSupported;}return isEventSupported;})();

<!doctype html><html dir=」ltr」 lang=」zh-CN」><head id=」head」><meta charset=」utf-8″/><title>司徒正美 </title>

<script type=」text/javascript」 charset=」utf-8″>window.onload = function(){

var isEventSupported = (function(){//使用模塊模式

var TAGNAMES = {//特定元素上的特定事件』select』:"input』,"change』:"input』,』submit』:"form』,"reset』:"form』,『error』:"img』,"load』:"img』,"abort』:"img』}

function isEventSupported(eventName, element) {

element = element || document.createElement(TAGNAMES[eventName] || 『div』);eventName = 『on』 + eventName;

// When using `setAttribute`, IE skips 「unload」, WebKit skips 「unload」 and 「resize」, whereas `in` 「catches」 thosevar isSupported = (eventName in element);//DOM0

if (!isSupported) {// if it has no `setAttribute` (i.e. doesn』t implement Node interface), try generic elementif (!element.setAttribute) {element = document.createElement(』div』);}if (element.setAttribute && element.removeAttribute) {element.setAttribute(eventName, 」);isSupported = typeof element[eventName] == 『function』;

// if property was created, 「remove it」 (by setting value to `undefined`)if (typeof element[eventName] != 『undefined』) {element[eventName] = void 0;}element.removeAttribute(eventName);}}

element = null;return isSupported;}return isEventSupported;})();function w(name, element) {document.write(name + 『: 『 + (isEventSupported(name, element) 『<span style=」background-color:green;color:white;」>true</span>』: 『<span style=」background-color:red;color:white;」>false</span>』) + 『<br>』);}

document.write(』<pre>』 + isEventSupported + 『</pre><br><br>』);

document.write(』<h2>Mouse events:</h2>』);

w(』click』);w(』dblclick』);w(』mousedown』);w(』mouseup』);w(』mouseover』);w(』mousemove』);w(』mouseout』);

document.write(』<h2>Key events:</h2>』);

w(』keypress』);w(』keydown』);w(』keyup』);

document.write(』<h2>HTML events</h2>』);

w(』load』);w(』unload』, window);w(』abort』);w(』error』);

document.write(』<h2>View events</h2>』);

w(』resize』, window);w(』scroll』);

document.write(』<h2>Form events:</h2>』);

w(』submit』);w(』reset』);

document.write(』<h2>Form controls』 events:</h2>』);

w(』select』);w(』change』);

document.write(』<h2>Activation events:</h2>』);

w(』focus』);w(』blur』);

document.write(』<h2>MSHTML DOM events:</h2>』);

w(』cut』);w(』copy』);w(』paste』);w(』beforecut』);w(』beforecopy』);w(』beforepaste』);w(』afterupdate』);w(』beforeupdate』);w(』cellchange』);w(』dataavailable』);w(』datasetchanged』);w(』datasetcomplete』);w(』errorupdate』);w(』rowenter』);w(』rowexit』);w(』rowsdelete』);w(』drag』);w(』dragstart』);w(』dragenter』);w(』dragover』);w(』dragleave』);w(』dragend』);w(』drop』);w(』selectstart』);w(』mouseenter』);w(』mouseleave』);w(』activate』);w(』beforeactivate』);w(』deactivate』);w(』beforedeactivate』);w(』focusin』);w(』focusout』);w(』stop』, document);w(』readystatechange』);w(』beforeprint』, document.body);w(』afterprint』, document.body);w(』beforeunload』, window);

document.write(』<h2>Unexistent (most likely) events:</h2>』);

w(』click2′);w(』foobarbaz』);

document.write(』<h2>Unexistent in Opera <=10a</h2>』);

w(』contextmenu』);

document.write(』<h2>iPhone touch/gesture events</h2>』);

w(』touchstart』);w(』touchend』);w(』touchmove』);w(』touchcancel』);

document.write(』<br>』);

w(』gesturestart』);w(』gesturechange』);w(』gestureend』);

document.write(』<h2>HTML5 events</h2>』);

w(』hashchange』, document.body);w(』online』, document.body);w(』offline』, document.body);w(』message』, window);w(』undo』, document.body);w(』redo』, document.body);w(』storage』, window);w(』popstate』, window);

w(』canplay』, document.createElement(』video』));w(』seeking』, document.createElement(』video』));w(』seekend』, document.createElement(』video』));

document.write(』<h2>Proprietary</h2>』);

w(』pageshow』, window);w(』pagehide』, window);

};</script>

</head><body>

</body></html>

連HTML5與iPhone touch的一些專有事件也能檢測到。

在jQuery1.4α2中也支持這種特性偵探了,不過用的是早期版本,不如上面寫出來的那個!

//jQuery1.4α2var eventSupported = function( eventName ) {var el = document.createElement(」div」);eventName = 「on」 + eventName;

var isSupported = (eventName in el);if ( !isSupported ) {el.setAttribute(eventName, 「return;」);isSupported = typeof el[eventName] === 「function」;}el = null;

return isSupported;};在未來jQuery技術方面,如果我們無法擺脫那些舊瀏覽器的話,事情可能沒多少改變,不過,即使現在,在那些更好的瀏覽器身上,我們也已經看到一些令人振奮的東西,我期待看到一些全新的東西。

Webkit引擎開發團隊已經做在CSS動畫方面做了很多工作,他們甚至將觸角伸向圖形硬體來實現炫目的視覺效果。Firefox, Safari, and Chrome 正在 JavaScript引擎方面你追我趕,而眾多JavaScript 庫也在性能上大幅提升。我們會開到越來越多的 HTML 5元素的使用,如 Canvas, 音頻,視頻。Web 字體方面也將更加完善,不管從技術方面還是版權方面。可以肯定的是,未來的Web會讓人驚異。

版權聲明:轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明文章引用地址:http://www.iefans.net/jiance-liulanqi-shijian-chuli/ 作者:iefans
推薦閱讀:

查看原文 >>
相关文章