JavaScript event bindings and in-depth

Source: Internet
Author: User
Tags tagname

There are two types of event bindings: Traditional event binding (inline model, script model), and modern event binding

(DOM2-level model). Modern event binding provides more powerful and convenient functionality on traditional bindings.


A Issues with traditional event bindings
Traditional event binding has inline model and script model, inline model we do not discuss, rarely use. First Look
Script model, the script model assigns a function to an event handler function.

    1. var box = document.getElementById (' box '); Get element
    2. Box.onclick = function () {//Element click Trigger Event
    3. Alert (' Lee ');
    4. };

Issue one: An event handler function triggers two events

    1. Window.onload = function () {//First set of program project or first JS file
    2. Alert (' Lee ');
    3. };
    4. Window.onload = function () {//second set of program project or second JS file
    5. Alert (' Mr.Lee ');
    6. };

When two sets of programs or two JS files are executed simultaneously, the latter one will completely overwrite the previous one. Lead
The window.onload in front has completely failed.


To solve the coverage problem, we can solve it this way:

    1. Window.onload = function () {//The first event to be executed will be overwritten
    2. Alert (' Lee ');
    3. };
    4. if (typeof window.onload = = ' function ') {//Before judging if there is window.onload
    5. var saved = null; Create a Save
    6. saved = window.onload; Save the previous window.onload.
    7. }
    8. Window.onload = function () {//FINAL one to execute event
    9. if (saved) saved (); Perform a previous event
    10. Alert (' Mr.Lee '); Code to execute this event
    11. };

Issue two: Event switcher

    1. Box.onclick = Toblue; First execution Boblue ()
    2. function tored () {
    3. This.classname = ' red ';
    4. This.onclick = Toblue; Execute Toblue () for the third time, then switch back and forth
    5. }
    6. function Toblue () {
    7. This.classname = ' Blue ';
    8. This.onclick = tored; Second Execution tored ()
    9. }

There are some problems with this switch when it expands:
1. If an execution function is added, it will be overwritten

    1. Box.onclick = Toalert; The added function
    2. Box.onclick = Toblue; Toalert is covered.

2. If the overwrite problem is resolved, it must include simultaneous execution, but a new problem

    1. Box.onclick = function () {//included in, but less readable
    2. Toalert (); The first time will not be overwritten, but the second time is overwritten
    3. Toblue.call (this); You must also pass this to the switcher.
    4. };

Three issues covered: coverage, readability, this delivery problem. Let's create a custom thing
To solve the above three problems.

    1. function addevent (obj, type, fn) {//Replace traditional event handler
    2. var saved = null; Save event handlers for each trigger
    3. if (typeof obj[' on ' + type] = = ' function ') {//Judging is not an event
    4. Saved = obj[' on ' + type]; If there is, save it.
    5. }
    6. obj[' on ' + type] = function () {///Then Execute
    7. if (saved) saved (); Perform the previous
    8. Fn.call (this); Execute the function and pass this to the past
    9. };
    10. }
    11. addevent (window, ' Load ', function () {///execute to
    12. Alert (' Lee ');
    13. });
    14. addevent (window, ' Load ', function () {///execute to
    15. Alert (' Mr.Lee ');
    16. });

PS: The above-written custom event handler, there is another problem is not handled, that is, two of the same function name
function is incorrectly registered for two or more times, you should block out the excess. Then we need to move the event handler into
Line traversal, if a function name with the same name is not added. (We don't do it here.)

    1. addevent (window, ' Load ', init); Register for the first time
    2. addevent (window, ' Load ', init); Register the second time, should ignore
    3. function init () {
    4. Alert (' Lee ');
    5. }

Use the custom event function to register to the switcher to see the effect:

    1. addevent (window, ' Load ', function () {
    2. var box = document.getElementById (' box ');
    3. addevent (box, ' click ', Toblue);
    4. });
    5. function tored () {
    6. This.classname = ' red ';
    7. Addevent (This, ' click ', Toblue);
    8. }
    9. function Toblue () {
    10. This.classname = ' Blue ';
    11. Addevent (This, ' click ', tored);
    12. }

PS: When you click a lot of many times after switching, the browser dies directly, or an error pops up: Too much
Recursion (too many recursion). The main reason is that every time the event is switched, it is saved and no useless
removed, resulting in the accumulation of more, the last card to die.

    1. function removeevent (obj, type) {
    2. if (obj[' on '] + type) obj[' on ' + type] = NULL; Delete event handler function
    3. }

The above delete event handler is just a one-size-fits-all delete, which resolves the card and too many recursive
Problem. But the other event handlers are also deleted, resulting in the final result not getting what they want. If you want to
To delete only the event handlers in the specified function, you need to traverse and find. (We don't do it here.)


Two Event handling function
The "DOM2 level event" defines two methods for adding events and deleting event handlers:
AddEventListener () and RemoveEventListener (). Both methods are included in all DOM nodes, and it
We all accept 3 parameters; The event name, function, bubbling, or captured Boolean value (true means capture, false for bubbling).

    1. Window.addeventlistener (' Load ', function () {
    2. Alert (' Lee ');
    3. }, False);
    4. Window.addeventlistener (' Load ', function () {
    5. Alert (' Mr.Lee ');
    6. }, False);

The ps:w3c of modern event binding is better than our custom: 1. No customization is required; 2. Can shield the phase
the same function; 3. You can set bubbles and captures.

    1. Window.addeventlistener (' Load ', init, false); For the first time.
    2. Window.addeventlistener (' Load ', init, false); It's been blocked for the second time.
    3. function init () {
    4. Alert (' Lee ');
    5. }

Event switcher

    1. window.addeventlistener (' Load ', function  ()  { 
    2. var box =  document.getElementById (' box ');  
    3. box.addeventlistener (' click ', function  ()  {  Will not be mistakenly deleted  
    4. alert (' Lee ');  
    5. }, false);  
    6. box.addeventlistener (' click ',  toblue, false);  //Introduction switch is not too much recursive card dead  
    7. }, false);  
    8. function  Tored ()  { 
    9. this.classname =  ' red ';  
    10. this.removeeventlistener (' click ',  tored, false);  
    11. this.addeventlistener (' click ',  toblue, false);  
    12. function toblue ()  { 
    13. this.classname =  ' Blue ';  
    14. this.removeeventlistener (' click ',  toblue, false);  
    15. this.addeventlistener (' click ',  tored, false);  

Setting the bubbling and capturing stages
In the previous chapter we learned about event bubbling, which is triggered from inside to outside. We can also use the event object to block
Bubbling at a certain stage. Then the modern event bindings can set bubbles and captures.

    1. Document.addeventlistener (' click ', function () {
    2. Alert (' Document ');
    3. }, True); Sets the Boolean value to True to capture the
    4. Box.addeventlistener (' click ', function () {
    5. Alert (' Lee ');
    6. }, True); Set the Boolean value to False to bubble

Three IE event handler function
IE implements two methods similar to the one in the DOM: Attachevent () and DetachEvent (). These two methods accept
Same parameter: event name and function.
In the use of these two sets of functions, the first to say the difference: 1. IE does not support capture, only supports bubbling; 2. IE add
The event cannot mask repeated functions; 3. The this in IE points to a window instead of a DOM object. 4. In traditional matters
, IE is not acceptable to the event object, but using Attchevent () can, but there are some differences.

    1. Window.attachevent (' onload ', function () {
    2. var box = document.getElementById (' box ');
    3. Box.attachevent (' onclick ', toblue);
    4. });
    5. function tored () {
    6. var that = window.event.srcElement;
    7. That.classname = ' red ';
    8. That.detachevent (' onclick ', tored);
    9. That.attachevent (' onclick ', toblue);
    10. }
    11. function Toblue () {
    12. var that = window.event.srcElement;
    13. That.classname = ' Blue ';
    14. That.detachevent (' onclick ', toblue);
    15. That.attachevent (' onclick ', tored);
    16. }

Ps:ie does not support capture, no solution. IE cannot be masked and needs to be expanded individually or custom event handling. IE cannot
Pass this and you can call the past.

    1. Window.attachevent (' onload ', function () {
    2. var box = document.getElementById (' box ');
    3. Box.attachevent (' onclick ', function () {
    4. Alert (This = = = window); This points to the window
    5. });
    6. });
    7. Window.attachevent (' onload ', function () {
    8. var box = document.getElementById (' box ');
    9. Box.attachevent (' onclick ', function () {
    10. Toblue.call (box); Direct this to the past
    11. });
    12. });
    13. function Tothis () {
    14. alert (this.tagname);
    15. }

In traditional bindings, IE is not able to accept the event object as a pass-through, but if you use the
Attachevent () can.

    1. Box.onclick = function (evt) {
    2. alert (EVT); Undefined
    3. }
    4. Box.attachevent (' onclick ', function (evt) {
    5. alert (EVT); Object
    6. alert (Evt.type); Click
    7. });
    8. Box.attachevent (' onclick ', function (evt) {
    9. Alert (evt.srcelement = = = box); True
    10. Alert (window.event.srcElement = = = box); True
    11. });

Finally, in order for IE and the Internet Explorer to be compatible with this event switcher, we can write the following method:

  1. function addevent (obj, type, fn) {//Add event compatible
  2. if (Obj.addeventlistener) {
  3. Obj.addeventlistener (type, FN);
  4. } else if (obj.attachevent) {
  5. Obj.attachevent (' on ' + type, fn);
  6. }
  7. }
  8. function removeevent (obj, type, fn) {//Remove event compatible
  9. if (Obj.removeeventlistener) {
  10. Obj.removeeventlistener (type, FN);
  11. } else if (obj.detachevent) {
  12. Obj.detachevent (' on ' + type, fn);
  13. }
  14. }
  15. function Gettarget (evt) {//Get event Target
  16. if (evt.target) {
  17. return evt.target;
  18. } else if (window.event.srcElement) {
  19. return window.event.srcElement;
  20. }
  21. }

PS: Invoke Ignore, IE compatible event, if you want to pass this, change to call can.
The event binding functions in Ps:ie attachevent () and detachevent () may not be used in practice, with several
Cause: 1. IE9 will fully support the event binding function in the universal, 2. The event binding function of IE cannot pass this;3. Ie
The event binding function does not support capture; 4. After the same function is registered, it is not masked; 5. There is a memory leak problem.
As for how to replace it, we will discuss it in the course of future projects.


Four Additional additions to the event object
A property is provided in the Relatedtarget: This property can be used in mouseover and mouseout events
Gets the DOM object from where and from where it was moved.

    1. Box.onmouseover = function (evt) {//mouse move into box
    2. alert (evt.relatedtarget); Gets the element object that was recently moved into box
    3. }//span
    4. Box.onmouseout = function (evt) {//mouse move out box
    5. alert (evt.relatedtarget); Gets the element object that moved out of box most recently
    6. }//span

IE provides two sets of properties for moving in and out: Fromelement and toelement, respectively, corresponding to MouseOver
and Mouseout.

    1. Box.onmouseover = function (evt) {//mouse move into box
    2. alert (window.event.fromElement.tagName); Gets the nearest element object span moved into box
    3. }
    4. Box.onmouseout = function (evt) {//mouse move into box
    5. alert (window.event.toElement.tagName); Gets the nearest element object span moved into box
    6. }

Ps:fromelement and toelement do not have any meaning if they correspond to the opposite mouse events respectively.


All that's left to do is cross-browser compatible:

    1. function Gettarget (evt) {
    2. var e = evt | | window.event; Get Event Object
    3. if (e.srcelement) {//If srcelement is supported, indicates IE
    4. if (E.type = = ' MouseOver ') {//if it is over
    5. return e.fromelement; Just use the From
    6. } else if (E.type = = ' mouseout ') {//if it is out
    7. return e.toelement; Just use the To
    8. }
    9. } else if (e.relatedtarget) {//If Relatedtarget is supported, the
    10. return e.relatedtarget;
    11. }
    12. }

Sometimes we need to block the default behavior of the event, such as: The default behavior of a hyperlink and then jump to the point
The page is set. This prevents the default behavior from blocking the jump, and implements the custom action.
The default behavior of canceling an event is also a non-canonical practice, which is to return false.

    1. Link.onclick = function () {
    2. Alert (' Lee ');
    3. return false; Give a fake directly, you will not jump.
    4. };

PS: Although return false; can implement this function, but there is a loophole; first: it must be written to the last, which causes
After execution of the middle code, it is possible to perform a return false; second: return false writes to the last
The definition operation is invalidated. So, the best way to do this is to block the default behavior at the top, and you can do it later
Code.

    1. Link.onclick = function (evt) {
    2. Evt.preventdefault (); Stop the default behavior and place it wherever you are
    3. Alert (' Lee ');
    4. };
    5. Link.onclick = function (evt) {//ie, blocking default behavior
    6. Window.event.returnValue = false;
    7. Alert (' Lee ');
    8. };

Cross-Browser compatible

    1. function Predef (evt) {
    2. var e = evt | | window.event;
    3. if (E.preventdefault) {
    4. E.preventdefault ();
    5. } else {
    6. E.returnvalue = false;
    7. }
    8. }

Context Menu Event: ContextMenu, when we right-click on a webpage, it automatically appears with Windows
Menu. Then we can use the ContextMenu event to modify the menu we specified, but only if you right-click the default
The behavior is cancelled out.

    1. addevent (window, ' Load ', function () {
    2. var text = document.getElementById (' text ');
    3. Addevent (text, ' ContextMenu ', function (evt) {
    4. var e = evt | | window.event;
    5. Predef (e);
    6. var menu = document.getElementById (' menu ');
    7. Menu.style.left = e.clientx + ' px ';
    8. Menu.style.top = e.clienty + ' px ';
    9. menu.style.visibility = ' visible ';
    10. Addevent (document, ' click ', function () {
    11. document.getElementById (' MyMenu '). style.visibility = ' hidden ';
    12. });
    13. });
    14. });

Ps:contextmenu events are common, which leads directly to a more stable browser compatibility.


Pre-uninstallation event: Beforeunload, this event can help you leave this page with the appropriate prompt, "away from
"or" return "operation.

    1. addevent (window, ' beforeunload ', function (evt) {
    2. Predef (EVT);
    3. });

Mouse wheel (mousewheel) and dommousescroll to get the mouse up and down the scroll wheel distance.

    1. Addevent (document, ' MouseWheel ', function (evt) {//non-Firefox
    2. Alert (GETWD (EVT));
    3. });
    4. Addevent (document, ' Dommousescroll ', function (evt) {//Firefox
    5. Alert (GETWD (EVT));
    6. });
    7. function Getwd (evt) {
    8. var e = evt | | window.event;
    9. if (E.wheeldelta) {
    10. return E.wheeldelta;
    11. } else if (E.detail) {
    12. Return-evt.detail * 30; Maintain the unity of computation
    13. }
    14. }

PS: Through browser detection you can determine that Firefox only executes Dommousescroll.


The domcontentloaded event and ReadyStateChange event, about Dom loading, about the
The contents of the two events are very numerous and complex, and we will first point here and discuss them in detail during the course of the project.

JavaScript event bindings and in-depth

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.