Cross-browser javascript Event System

Source: Internet
Author: User

However, in essence, the father of javascript cannot master all of this. The website he supports is not powerful enough to allow competitors to use its products. Microsoft developed a JScript, the dead Macromedia made an ActionScript, and there are more. I heard that this branch is quite complicated. However, to use the built-in DOM event model of the browser, the first consequence is that to use it, you must use a DOM object, window, document, or element node, the second consequence is that each browser has different DOM support and cannot ensure the consistency of the event model. The third is that the DOM-based object can easily cause circular reference. After Microsoft won the first browser war, it basically did not update its DOM model. It is divided into two camps with the standard browser, which is constantly updated to w3c, ecma, and other standards. However, the standard browser is not a rock block, for example, FF does not support mousewheel but DOMMouseScroll, and opera's contextmenu is uncontrollable. We need to implement it ourselves. Currently, dual-master implements the DOM2 event model. Microsoft is headed by attachEvent. The standard is addeventListener, which allows the same element to bind multiple Event Callback functions of the same type. Many addEvent functions on the Internet are made of them, but they are not reliable. First, the callback function of IE is not forced to bind event objects, the standard browser is the first parameter of the strong dance music, that is, the event object. Although we can use the call function to implement forced binding, the IE event object is different from the standard one, there is a lot of work to do here. The other is the execution sequence of the callback function. There is no rule for IE, and the standard is to execute the code in the order of binding. Therefore, these two functions are also denied. I plan to use the most primitive onXXXX implementation. When I bind multiple functions, I will put them into a function and a for loop.
Copy codeThe Code is as follows:
<! Doctype html>
<Html lang = "en">
<Head>
<Meta charset = "UTF-8"/>
<Meta content = "IE = 8" http-equiv = "X-UA-Compatible"/>
<Title> Event System by situ zhengmei </title>
<Style type = "text/css">
# Target {
Width: 400px;
Height: 100px;
Background: blue;
}
</Style>
<Script type = "text/javascript">
Var dom = {};
Array. prototype. indexOf = function (el, index ){
Var n = this. length >>> 0,
I = index = null? 0: index <0? Math. max (0, n + index): index;
For (; I <n; I ++)
If (I in this & this [I] === el) return I;
Return-1;
};
// Http://msdn.microsoft.com/zh-cn/library/bb383786.aspx
// Remove the first match of an element in the Array object.
Array. prototype. remove = function (item ){
Var index = this. indexOf (item );
If (index! =-1) return this. removeAt (index );
Return null;
};
// Remove the elements at the specified position in the Array object.
Array. prototype. removeAt = function (index ){
Return this. splice (index, 1)
};
Dom. attachEvent = function (el, type, handler ){
// Set an Object-type private definition attribute events on each element
If (! El. events) el. events = {};
// This object has many keys of the event type and the value is the attribute of the Function Array.
Var handlers = el. events [type];
If (! Handlers ){
Handlers = el. events [type] = [];
// If it was originally bound to an event in onXXXX mode, set it to the first element of the event array.
If (el ["on" + type]) {
Handlers [0] = el ["on" + type];
}
}
// Add a callback function
Handlers. push (handler)
// Bind our processing functions in onXXXX Mode
El ["on" + type] = dom. handleEvent;
};
Dom. detachEvent = function (el, type, handler ){
If (el. events & el. events [type]) {
El. events [type]. remove (handler)
}
}
Dom. handleEvent = function (event ){
Var returnValue = true;
// Grab the event object (IE uses a global event object)
Event = event | fixEvent (this. ownerDocument | this.doc ument | this). parentWindow | window). event );
// Get a reference to the hash table of event handlers
Var handlers = this. events [event. type];
// Execute each event handler
For (var I = 0, n = handlers. length; I <n; I ++ ){
If (handlers [I] (event) === false ){
ReturnValue = false;
}
}
Return returnValue;
};
Function fixEvent (event ){
// Add W3C standard event methods
Event. preventDefault = fixEvent. preventDefault;
Event. stopPropagation = fixEvent. stopPropagation;
Return event;
};
FixEvent. preventDefault = function (){
This. returnValue = false;
};
FixEvent. stopPropagation = function (){
This. cancelBubble = true;
};
Var $ = function (id ){
Return document. getElementById (id)
}
Window. onload = function (){
Var a = function (e ){
$ ("P"). innerHTML = e. clientX + "" + e. clientY
}
Dom. attachEvent ($ ("target"), "mousemove", );
SetTimeout (function (){
Dom. detachEvent ($ ("target"), "mousemove", );
}, 10*1000)
}
</Script>
</Head>
<Body>
<Div id = "target">
</Div>
<P id = "p"> </p>
</Body>
</Html>

Let's review the above process. This event system is actually a revision of addEvent of Dean's great god.
Set an object as a namespace.
Extends the Array.
The attachEvent function is used to bind events. Set an events attribute for the object to bind the event, and place the callback function based on the event type, sometimes we may bind two or more onclick events to the same element, so they must be an array. Finally, add an onXXXX attribute using the original DOM0 method.
The detachEvent function is used to detach events, that is, to remove the array elements of the corresponding types on events.
HandleEvent executes the callback function. We bound a global function in the form of onXXXX. Its function is to obtain and correct the event object, and then obtain all the callback functions corresponding to this event type, then execute the event objects as their first parameters. The last step is to handle the bubbles.
FixEvent fixes the event object. Basically, there are two methods to make IE have a standard browser.
For general applications, it is enough. But if the pursuit is complete. We still have a lot to use. First, it is inappropriate to put the huge object events on the element, which is not conducive to centralized management. 2. fixEvent is incomplete. properties in standard browsers, such as target, pageX/Y, cannot be used in IE.
The first is the handleEvent function. Now, both the standard browser and the IE event object need to be corrected, and the IE currentTarget value is also corrected for each call.
Copy codeThe Code is as follows:
Dom. handleEvent = function (event ){
Event = event | window. event
Event = dom. fixEvent (event );
Event. currentTarget = this; // corrected currentTarget
Var returnValue = true;
Var handlers = this. events [event. type];
For (var I = 0, n = handlers. length; I <n; I ++ ){
If (handlers [I] (event) === false ){
ReturnValue = false;
}
}
Return returnValue;
};

When we introduce the new fixEvent function, we will first repeat the pseudo event objects I have plagiarized from jQuery.
Copy codeThe Code is as follows:
Dom. oneObject = function (arr, val ){
Var result = {}, value = val! = Undefined? Val: 1;
For (var I = 0, n = arr. length; I <n; I ++)
Result [arr [I] = value;
Return result;
};
Dom. mixin = function (result, source ){
If (arguments. length = 1 ){
Source = result;
Result = dom;
}
If (result & source ){
For (var key in source)
Source. hasOwnProperty (key) & (result [key] = source [key]);
}
If (arguments. length> 2 ){
Var others = []. slice. call (arguments, 2 );
For (var I = 0, n = others. length; I <n; I ++ ){
Result = arguments. callee (result, others [I]);
}
}
Return result;
}
Var MouseEventOne = dom. oneObject (["click", "dblclick", "mousedown ",
"Mousemove", "mouseout", "mouseover", "mouseup"], "[object MouseEvent]");
Var HTMLEventOne = dom. oneObject (["abort", "blur", "change", "error", "focus ",
"Load", "reset", "resize", "scroll", "select", "submit", "unload"], "[object Event]");
Var KeyboardEventOne = dom. oneObject (["keyup", "keydown", "keypress",],
"[Object KeyboardEvent]");
Var EventMap = dom. mixin ({}, MouseEventOne, HTMLEventOne, KeyboardEventOne)
Var fn = "prototype ";
Dom. Event = function (src ){
If (! This. preventDefault ){
Return new dom. Event [fn]. init (src );
}
};
Function returnFalse (){
Return false;
}
Function returnTrue (){
Return true;
}
// Http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
Dom. Event [fn] = {
Init: function (src ){
// If the input is an event object
If (src & src. type ){
This. originalEvent = src;
This. type = src. type;
// If the input is an event type
} Else {
This. type = src;
}
This. timeStamp = new Date (). valueOf ();
This ["expando"] = true;
},
// Http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/events.html#Conformance
ToString: function (){
Return EventMap [this. type] | "[object Event]"
},
PreventDefault: function (){
This. isdefapreprevented = returnTrue;
Var e = this. originalEvent;
If (! E ){
Return;
}
// If preventDefault exists, call it.
If (e. preventDefault ){
E. preventDefault ();
}
// If returnValue exists, set it to false.
E. returnValue = false;
},
StopPropagation: function (){
This. isPropagationStopped = returnTrue;
Var e = this. originalEvent;
If (! E ){
Return;
}
// If preventDefault exists, call it.
If (e. stopPropagation ){
E. stopPropagation ();
}
// If returnValue exists, set it to true.
E. cancelBubble = true;
},
StopImmediatePropagation: function (){
This. isImmediatePropagationStopped = returnTrue;
This. stopPropagation ();
},
Isdefapreprevented: returnFalse,
IsPropagationStopped: returnFalse,
IsImmediatePropagationStopped: returnFalse
};
Dom. Event [fn]. init [fn] = dom. Event [fn];

This constructor only implements a few methods of the W3C event model. Where are the attributes? Don't rush. We can copy them in the fixEvent method. To distinguish between a native event object and a pseudo event object, we add an expando attribute on it.
Copy codeThe Code is as follows:
Var buttonMap = {
1:1,
4: 2,
2: 3
}
Dom. fixEvent = function (event ){
If (event ["expando"]) {
Return event;
}
Var originalEvent = event
Event = dom. Event (originalEvent );
For (var prop in originalEvent ){
If (typeof originalEvent [prop]! = "Function "){
Event [prop] = originalEvent [prop]
}
}
// If the target attribute does not exist, add
If (! Event.tar get ){
Event.tar get = event. srcElement | document;
}
// If the event source object is a text node, place the parent Element
If (event.tar get. nodeType = 3 ){
Event.tar get = event.tar get. parentNode;
}
// If the relatedTarget attribute does not exist, add
If (! Event. relatedTarget & event. fromElement ){
Event. relatedTarget = event. fromElement = event.tar get? Event. toElement: event. fromElement;
}
// If pageX/Y does not exist, use clientX/Y for a pair.
If (event. pageX = null & event. clientX! = Null ){
Var doc = document.doc umentElement, body = document. body;
Event. pageX = event. clientX + (doc & doc. scrollLeft | body & body. scrollLeft | 0)-(doc & doc. clientLeft | body & body. clientLeft | 0 );
Event. pageY = event. clientY + (doc & doc. scrollTop | body & body. scrollTop | 0)-(doc & doc. clientTop | body & body. clientTop | 0 );
}
// Add the which event for the keyboard event
If (! Event. which & (event. charCode | event. charCode = 0 )? Event. charCode: event. keyCode )){
Event. which = event. charCode | event. keyCode;
}
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
If (! Event. metaKey & event. ctrlKey ){
Event. metaKey = event. ctrlKey;
}
// Determine which key the mouse event is pressed, 1 = left; 2 = middle; 3 = right
If (! Event. which & event. button! = Undefined ){
Event. which = buttonMap [event. button]
}
Return event;
}

Do not hesitate to copy the jQuery method, because among all class libraries, jQuery is the best method to extract.
Now we have basically solved one of the two questions raised in the middle section of the article. To solve the first problem, we need to introduce the cache system. This will be left for the next part.
<! Doctype html> <ptml lang = "en"> <pead> <meta charset = "UTF-8"/> <meta content = "IE = 8" http-equiv = "X-UA -Compatible "/> <title> Event by situ zhengmei </title> <style type =" text/css "> # target {width: 400px; height: 100px; background: blue ;} </style> </pead> <body> <p id = "p"> show the mouse position </p> press the keyboard key </body> </ptml>
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]

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.