Create a cross-browser event processing mechanism using JavaScript [produced by blue-Dream]

Source: Internet
Author: User

Using a class library can easily solve compatibility issues. But what is the mechanism behind this? Let's talk about it a little bit.

First, Dom level2 defines two functions for event processing: addeventlistener and removeeventlistener, both of which come from the eventtarget interface.

CopyCode The Code is as follows: element. addeventlistener (eventname, listener, usecapture );
Element. removeeventlistener (eventname, listener, usecapture );

The eventtarget interface is usually implemented from the node or window interface, that is, the so-called Dom element.
For example, you can use addeventlistener to add a listener for window.Copy codeThe Code is as follows: function loadhandler (){
Console. Log ('the page is loaded! ');
}
Window. addeventlistener ('load', loadhandler, false );

Removeeventlistener can also be used to remove a listener. You only need to pay attention to the removed handle and the added handle.
Window. removeeventlistener ('load', loadhandler, false );

If we live in the perfect world, it is estimated that the event function is over.
However, this is not the case. Because IE is unique, the attachevent and detachevent functions are defined using the msdhtml Dom to replace addeventlistener and removeeventlistener.
There are many differences between functions, making the entire event mechanism very complex.
So what we need to do is actually to handle the differences in event processing between IE and W3C standards.

You can add or remove a listener under IE to writeCopy codeThe Code is as follows: function loadhandler (){
Alert ('the page is loaded! ');
}
Window. attachevent ('onload', loadhandler); // Add a listener
Window. detachevent ('onload', loadhandler); // remove the listener

from the appearance, we can see the difference between IE and W3C:
1. there is an additional "on" prefix before the event.
2. remove the third parameter usecapture.
the real difference is far more than that. the analysis will continue later. therefore, we can easily abstract a common function copy Code the code is as follows: function addlistener (element, eventname, Handler) {
If (element. addeventlistener) {
element. addeventlistener (eventname, handler, false);
}< br> else if (element. attachevent) {
element. attachevent ('on' + eventname, Handler);
}< br> else {
element ['on' + eventname] = handler;
}< BR >}< br> function removelistener (element, eventname, Handler) {
If (element. addeventlistener) {
element. removeeventlistener (eventname, handler, false);
}< br> else if (element. detachevent) {
element. detachevent ('on' + eventname, Handler);
}< br> else {
element ['on' + eventname] = NULL;
}< BR >}

The above functions have two points to note:
1. The W3C standard should be determined first for the first branch, because IE is gradually approaching the standard. The second branch monitors IE.
2. The third branch is left to browsers that neither Add/Remove eventlistener nor attach event are supported.

Performance Optimization
For the above functions, we use "RunTime" for monitoring. that is, branch monitoring is required for each binding event. we can change it to "before running" to determine the compatible function. instead of monitoring each time.
In this way, we need to use a DOM element for early detection. Here we choose document.doc umentelement. Why not use document. Body? Because document.doc umentelement already exists when document does not have ready, and document. Body does not exist before ready.
In this way, the function is optimized Copy code The Code is as follows: var addlistener, removelistener,
/* Test element */
Docel = document.doc umentelement;
// Addlistener
If (docel. addeventlistener ){
/* If 'addeventlistener 'exists on test element, define function to use 'addeventlistener '*/
Addlistener = function (element, eventname, Handler ){
Element. addeventlistener (eventname, handler, false );
};
}
Else if (docel. attachevent ){
/* If 'tachevent' exists on test element, define function to use 'tachevent '*/
Addlistener = function (element, eventname, Handler ){
Element. attachevent ('on' + eventname, Handler );
};
}
Else {
/* If neither methods exists on test element, define function to fallback strategy */
Addlistener = function (element, eventname, Handler ){
Element ['on' + eventname] = handler;
};
}
// Removelistener
If (docel. removeeventlistener ){
Removelistener = function (element, eventname, Handler ){
Element. removeeventlistener (eventname, handler, false );
};
}
Else if (docel. detachevent ){
Removelistener = function (element, eventname, Handler ){
Element. detachevent ('on' + eventname, Handler );
};
}
Else {
Removelistener = function (element, eventname, Handler ){
Element ['on' + eventname] = NULL;
};
}

This avoids the need to judge each binding.
It is worth mentioning that. the above Code actually has two serious injuries. in addition to increasing the number of codes, some users have used the hard drive test code. Our basic ideas are broken. If document.doc umentelement has the Add/Remove Method. the element must be available (although in most cases ). but this is obviously not safe enough.
Insecure Detection
The following two examples show that in some cases this detection is not safe enough.Copy codeThe Code is as follows: // in Internet Explorer
VaR xhr = new activexobject ('Microsoft. xmlhttp ');
If (xhr. Open) {}// Error
VaR element = Document. createelement ('P ');
If (element. offsetparent) {}// Error

For example, in IE7, typeof xhr. Open = 'unknown '. For details, refer to feature-detection.
Therefore, the detection method we advocate isCopy codeThe Code is as follows: var ishostmethod = function (object, methodname ){
VaR T = typeof object [methodname];
Return (t = 'function' | T = 'object ')&&!! Object [methodname]) | T = 'unknown ';
};

In this way, the above optimization function is improved to this way again.Copy codeThe Code is as follows: var addlistener, docel = document.doc umentelement;
If (ishostmethod (docel, 'addeventlistener ')){
/*...*/
}
Else if (ishostmethod (docel, 'tachevent ')){
/*...*/
}
Else {
/*...*/
}

Lost this pointer
This pointer processing. There is another difference between IE and W3C. In W3C, the pointer to the function is a DOM element bound to the handle. in IE, it always points to window.Copy codeThe Code is as follows: // IE
Document. Body. attachevent ('onclick', function (){
Alert (this = Window); // true
Alert (this = Document. Body); // false
});
// W3C
Document. Body. addeventlistener ('onclick', function (){
Alert (this = Window); // false
Alert (this = Document. Body); // true
});

This problem is not difficult to fix.Copy codeThe Code is as follows: if (ishostmethod (docel, 'addeventlistener ')){
/*...*/
}
Else if (ishostmethod (docel, 'tachevent ')){
Addlistener = function (element, eventname, Handler ){
Element. attachevent ('on' + eventname, function (){
Handler. Call (element, window. Event );
});
};
}
Else {
/*...*/
}

We only need to use a packaging function. then, the internal Department uses the call method to correct the pointer. in fact, we should have seen that a problem is also secretly corrected here. in ie, the event is not passed through the first function, but is left in the global environment. so we often write event = event | window. event code. the modification is also made here.
Corrected these main problems. Our function seems to be much more robust. We can pause and perform a simple test to test three points.
1. Compatibility with various browsers 2. This pointer pointing to compatibility 3. Compatibility with event parameter transfer.

The test code is as follows:Xmlns = "http://www.w3.org/1999/xhtml">

Test text

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.