JavaScript cross-browser event system _javascript Tips

Source: Internet
Author: User
Tags hasownproperty
But the actual JavaScript father can not dominate all of this, and his support of Netscape is not strong enough to allow competitors to obediently use its products, Microsoft has a JScript, dead Macromedia got a ActionScript, and more, I hear this branch is very complicated. But the first consequence of using the browser's built-in DOM event model is that you want to use it with a DOM object, a window,document or an element node, and the second consequence is that each browser has different support for the DOM, does not ensure that the event model is consistent, and the third is due to DOM object based , it is easy to create circular references. After Microsoft won its first browser war, it basically did not update its DOM model, and it was divided into two camps with "standard browsers", which are constantly updating to standards such as W3C,ECMA. But the standard browser is not a rock piece, such as FF does not support MouseWheel but Dommousescroll,opera ContextMenu is not controllable. We need to implement it ourselves. At the moment, the dual-owner implementation of the DOM2 event model, Microsoft is attachevent led, the standard is AddEventListener, allows the same element can be bound to multiple event callback functions of the same type. Many of the addevent functions on the web are made of them, but also unreliable, first of all, IE's callback function does not force binding event objects, and standard browser is strong dance the first parameter is the event object, although we can use the call function to implement force binding, but IE event objects and standard is not the same, There's a lot of work to be done here. Another, is the callback function of the execution order problem, IE is no rules, the standard is in the order of the binding execution. Therefore, these two functions are also denied. I'm going to do it with the most primitive onxxxx, when I bind multiple functions, I put them in a function, and a for loop is done.
Copy Code code as follows:

<!doctype html>
<meta charset= "Utf-8"/>
<meta content= "ie=8" http-equiv= "x-ua-compatible"/>
<title>event System by Masaki </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
Removes the first occurrence of an element in an Array object.
array.prototype.remove= function (item) {
var index = This.indexof (item);
if (index!==-1) return this.removeat (index);
return null;
};
Removes the element 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 on each element events
if (!el.events) el.events = {};
This object has many keys for the event type, and the value is the property of the function array
var handlers = El.events[type];
if (!handlers) {
Handlers = El.events[type] = [];
If it was originally bound to an event in a onxxxx way, then place it as the first element of the event array
if (el["on" + type]) {
Handlers[0] = el["on" + type];
}
}
Add callback function
Handlers.push (Handler)
Bind our handler functions in a onxxxx way
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.document | | 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 Consortium 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", a);
settimeout (function () {
Dom.detachevent ($ ("target"), "MouseMove", a);
},10*1000)
}
</script>
<body>
<div id= "Target" >
</div>
<p id= "P" ></p>
</body>

Let's review the process above and this event system is actually a revision of Dean's great God's addevent.
Sets an object that is a namespace.
Make some extensions to array.
The Attachevent function is used to bind events. The practice is to set an events attribute on the object that needs to bind the event, and then place the callback function by event type, because sometimes we may bind 2 or more onclick events to the same element, so they must be an array. Finally, add a Onxxxx property with the original method of DOM0.
The DetachEvent function is used to unload events by removing the array elements of the corresponding type on the events.
Handleevent executes the callback function. We bind a global function in the form of onxxxx, which is to get and fix the event object, then get all the callback functions for this event type, and then execute the event objects as their first argument in turn. Finally, deal with bubbles.
Fixevent fixes the event object. Basically, there are two ways that IE has a standard browser.
For general applications, it is sufficient. But if the pursuit is complete. We still have a lot of things to use. First of all, the events of this huge object on the element is very inappropriate, not conducive to centralized management. Second, fixevent is not complete, such as target,pagex/y, such as standard browser properties, in IE or not.
The first is the Handleevent function, which is now either standard browser or IE's event object to be fixed, and in each call for IE to modify its currenttarget value.
Copy Code code as follows:

Dom.handleevent = function (event) {
Event = Event | | Window.event
event = Dom.fixevent (event);
Event.currenttarget = this;//Revision 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 first introduce the pseudo event object that I stole from jquery.
Copy Code code 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 to 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 event object is passed in
if (src && src.type) {
This.originalevent = src;
This.type = Src.type;
If the event type is passed in
} 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.isdefaultprevented = Returntrue;
var e = this.originalevent;
if (!e) {
Return
}
If there is a preventdefault then call it
if (E.preventdefault) {
E.preventdefault ();
}
If there is a returnvalue then set it to False
E.returnvalue = false;
},
Stoppropagation:function () {
this.ispropagationstopped = Returntrue;
var e = this.originalevent;
if (!e) {
Return
}
If there is a preventdefault then call it
if (e.stoppropagation) {
E.stoppropagation ();
}
If there is a returnvalue then set it to True
E.cancelbubble = true;
},
Stopimmediatepropagation:function () {
this.isimmediatepropagationstopped = Returntrue;
This.stoppropagation ();
},
Isdefaultprevented:returnfalse,
Ispropagationstopped:returnfalse,
Isimmediatepropagationstopped:returnfalse
};
Dom. EVENT[FN].INIT[FN] = dom. EVENT[FN];

This constructor implements only a few of the methods of the event model of the consortium, where do those attributes go? In no hurry, we implement them in the Fixevent method by copying them. To distinguish between the native event object and the pseudo event object, we added a expando attribute to it.
Copy Code code 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 is not present, add a
if (!event.target) {
Event.target = Event.srcelement | | Document
}
If the event source object is a text node, the parent element is placed
if (Event.target.nodeType = = 3) {
Event.target = Event.target.parentNode;
}
If the Relatedtarget property does not exist, add a
if (!event.relatedtarget && event.fromelement) {
Event.relatedtarget = Event.fromelement = = Event.target? Event.toElement:event.fromElement;
}
If there is no pagex/y then combine clientx/y make a pair out
if (Event.pagex = = null && event.clientx!= null) {
var doc = document.documentelement, BODY = document.body;
Event.pagex = Event.clientx + (Doc && Doc.scrollleft | | body && Body.scrollleft | | 0)-(Doc && do C.clientleft | | Body && Body.clientleft | | 0);
Event.pagey = Event.clienty + (Doc && Doc.scrolltop | | body && Body.scrolltop | | 0)-(Doc && doc. ClientTop | | Body && Body.clienttop | | 0);
}
To add a which event to a 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 (with Ctrl for PCs ' s and Meta for Macs)
if (!event.metakey && event.ctrlkey) {
Event.metakey = Event.ctrlkey;
}
Determine what button 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 method of jquery, because in all class libraries, the jquery method is best extracted.
Now we have basically solved one of the two issues raised in the middle of the article. To solve the first one, we need to introduce a caching system. This is left in the next part of the story.
<!doctype html> <ptml lang= "en" > <pead> <meta charset= "Utf-8"/> <meta content= "ie=8" htt p-equiv= "X-ua-compatible"/> <title>event by Masaki </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//Removes the first occurrence of an element in an Array object. array.prototype.remove= function (item) {var index = This.indexof (item); if (index!==-1) return this.removeat (index); return null; }; Removes the element 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 OB on each elementThe private definition attribute of the Ject type events if (!el.events) el.events = {}; This object has many keys for the event type, and the value is the property of the function array var handlers = El.events[type]; if (!handlers) {handlers = El.events[type] = []; If it was originally bound to an event in a onxxxx manner, place it as the first element of the event array if (el["on" + type]) {handlers[0] = el[' on ' + type]; }///Add callback function Handlers.push (handler)//Bind our handler function in Onxxxx mode el["on" + type] = Dom.handleevent; }; Dom.detachevent = function (el, type, handler) {if (el.events && El.events[type]) {El.events[type].remove (Handl ER)} dom.handleevent = function (event) {event = Event | | window.event event = dom.fixevent (event); Event.currenttarget = this;//fixed 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; }; 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 is not present, add an if (!event.target) {event.target = Event.srcelement | | document to it; ///If the event source object is a text node, place its parent element if (Event.target.nodeType = 3) {event.target = Event.target.parentNode; //If no Relatedtarget property exists, add an if (!event.relatedtarget && event.fromelement) {Event.relatedtarget = event to it. Fromelement = = Event.target? Event.toElement:event.fromElement; }//If no pagex/y is present, then combine clientx/y to make a pair out if (Event.pagex = = null && event.clientx!= null) {var doc = Document.docu Mentelement, BODY = document.body; Event.pagex = Event.clientx + (Doc && Doc.scrollleft | | body && Body.scrollleft | | 0)-(Doc && do C.clientleft | | Body && Body.clientleft | | 0); Event.pagey = Event.clienty + (Doc && Doc.scrolltop | | body && Body.scrolltop | | 0)-(Doc && doc. CliEnttop | | Body && Body.clienttop | | 0); ///Add which event for keyboard events if (!event.which && (Event.charcode | | event.charcode = 0)? event.charCode:event.keyC Ode)) {Event.which = Event.charcode | | event.keycode; //ADD Metakey to Non-mac browsers (with Ctrl for PCs ' s and Meta for Macs) if (!event.metakey && Event.ctrlkey ) {Event.metakey = Event.ctrlkey; //Determine which key is pressed by the mouse event, 1 = = left; 2 = = middle; 3 = = Right if (!event.which && event.button!== undefined) {Event.which = Buttonmap[event.button]} Event } 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[ke Y]); } 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 event object is passed in (SRC && src.type) {this.originalevent = src; This.type = Src.type; If the event type is passed in {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.isdefaultprevented = Returntrue; var e = this.originalevent; if (!e) {return; ///If there is a preventdefault then call it if (E.preventdefault) {e.preventdefault (); ///If there is a returnvalue then set it to false e.returnvalue = false; }, Stoppropagation:function () {this.ispropagationstopped = Returntrue; var e = this.originalevent; if (!e) {return; ///If there is a preventdefault then call it if (e.stoppropagation) {e.stoppropagation (); ///If there is a returnvalue then set it to true e.cancelbubble = true; }, Stopimmediatepropagation:function () {this.isimmediatepropagationstopped = Returntrue; This.stoppropagation (); }, ISdefaultprevented:returnfalse, Ispropagationstopped:returnfalse, isimmediatepropagationstopped:returnfalse}; Dom. EVENT[FN].INIT[FN] = dom. EVENT[FN]; var $ = function (ID) {return document.getElementById (id)} window.onload = function () {var a = function (e) {$ (' P '). In nerhtml = E.pagex + "" "+e.pagey} dom.attachevent ($ (" target ")," MouseMove ", a); settimeout (function () {Dom.detachevent ($ ("target"), "MouseMove", a); },10*1000); Dom.attachevent (document, "KeyUp", function (e) {alert (e); Alert ("You are pressing" +string.fromcharcode (E.which) + "Key")}} </script> </pead> <body> <div id= "Target" > </div> <p id= "P" > show mouse position </p> <p> Please press the key of the keyboard </p> </body> </ptml>
[Ctrl + A All SELECT Note: If the need to introduce external JS need to refresh to perform]

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.