[JavaScript in front-end tutorials] 10_DOM programming details table operations and events

Posted by jamz310 on Mon, 27 Dec 2021 21:34:02 +0100

JavaScript from getting started to mastering video through train:

        [1-200] JavaScript video tutorial, from introduction to mastery, with more cases of practice, easy to understand!

        [201-300] JavaScript video tutorial, from introduction to mastery, with more cases of practice, easy to understand!

1, JavaScript operation table

1.1 operation table API

1. In the HTML DOM, some attributes and methods are provided for the table operation.

Unique attributes and methods of the table element node:

Property or methodexplain
captionHolds a reference to the < caption > element
tBodiesAn HTMLCollection collection that holds < tbody > elements
tFootHolds a reference to the < tFoot > element
tHeadHolds a reference to the < thead > element
createTHead()Create the < thead > element and return a reference
createTFoot()Create a < tFoot > element and return a reference
createTBody()Create a < tbody > element and return a reference
createCaption()Create a < caption > element and return a reference
deleteTHead()Delete the < thead > element
deleteTFoot()Delete the < tFoot > element
deleteCaption()Delete the < caption > element

2. Attributes and methods added by < tbody > / < thead > / < tFoot > / < Table > elements

Property or methodexplain
rowsThe HTMLCollection that holds the rows in the specified element
deleteRow(pos)Deletes the row at the specified location
insertRow(pos)Inserts a row at a specified location in the rows collection and returns a reference

3. Attributes and methods added by < tr > element

Property or methodexplain
cellsHTMLCollection that holds cells in < tr > elements
deleteCell(pos)Deletes the cell at the specified location
insertCell(pos)Inserts a cell into the specified location of the cells collection and returns a reference

1.2 cases

Use the new API to dynamically create tables;

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* If we write the tag signature directly, this is the so-called tag selector */
        /* The selector {} adds a style to the specified label */
        /* Selector 1, selector 2 {} add styles to multiple specified elements */
        table,
        td,
        th {
            border: 1px solid black;
        }

        /* 
            In general: we set the width for the table;
            Generally, we set the height of the row;
         */
        table {
            /* border-collapse Border merge */
            border-collapse: collapse;
            margin: 0 auto;
            width: 800px;
            /* If we center the text in the table, the td cell will inherit the style */
            /* text-align: center;  */
        }

        tr {
            height: 38px;
        }

        caption {
            font-size: 40px;
            font-weight: bold;
            height: 80px;
            line-height: 80px;
        }

        /* tbody>tr    Select all the lines in tbody */
        tbody>tr:nth-child(odd) {
            background: #eee;
        }

        thead td {
            text-align: center;
            font-weight: bold;
        }
    </style>
</head>

<body>
    <table id="tab1">

    </table>
    <script>
        // Get the table element node
        var stuTable = document.getElementById("tab1");

        // Create thead, tbody
        var thead = stuTable.createTHead();
        var tbody = stuTable.createTBody();


        // Header data
        var headDatas = ['full name', 'subject', 'achievement', 'operation'];

        // Create a row in thead
        var theadTr = thead.insertRow(0);

        for (var i in headDatas) { //When using for in to traverse the array, the variable in front of in represents the subscript of the array
            // Get each header data
            // theadTr.insertCell(i) creates a row based on the subscript and inserts content into the row
            theadTr.insertCell(i).innerText = headDatas[i];;
        }

        // Analog data
        var datas = [{
                name: 'Zhang San',
                subject: 'language',
                score: 90
            },
            {
                name: 'Li Si',
                subject: 'mathematics',
                score: 80
            },
            {
                name: 'Wang Wu',
                subject: 'English',
                score: 99
            },
            {
                name: 'Ma Liu',
                subject: 'English',
                score: 100
            },
            {
                name: 'pseudo-ginseng',
                subject: 'English',
                score: 60
            },
            {
                name: 'Zhao Ba',
                subject: 'English',
                score: 70
            }
        ];

        // Based on the above data, generate rows, cells and data in tbody
        // If there are several elements in the data array, you should create several rows; Create as many cells as there are key vaues in each element
        for (var i in datas) { // Six student objects stored in data
            // Get each student object by subscript
            var stuInfo = datas[i];

            // Each student has a row of data
            var tbodyTr = tbody.insertRow(i);

            var index = 0;
            // Each student's data is a cell
            for (var j in stuInfo) { // j is the key of the string when traversing the object
                // j  "name"    "subject"   "score"
                tbodyTr.insertCell(index++).innerText = stuInfo[j];
            }

            tbodyTr.insertCell(index).innerHTML = "<a href='javascript:void(0)'>delete</a>";

        }
    </script>

</body>

</html>

2, JavaScript events (focus)

2.1 event introduction

The interaction between JavaScript and HTML is realized through events. Events are some actions executed by users or browsers themselves, such as click, mounseever, load... And the functions that respond to events are called event handling functions.

Events are the beating heart of JavaScript applications and the glue that holds everything together. An event occurs when we have some type of interaction with a Web page in a browser. An event may be a user's click on something, mouse over a specific element, or press a key on the keyboard. Events may also be events that occur in a Web browser, such as the completion of a Web page loading, or the user scrolling the window or changing the window size.

Event: trigger response mechanism

Three elements of the event:

  • Event source: the element that triggers (is) the event

  • Event name: click event

  • Event handler: code to be executed after the event is triggered (in functional form)

Common events:

When the mouse clicks somewhere, something happens

When the mouse moves into a place, something happens

When the page is loaded, something happens

When the input box gets the cursor, something happens

When the input box loses its cursor, something happens

When you press a key, something happens

By using JavaScript, you can listen for specific events and specify that certain events occur in response to them. JavaScript events are a series of actions caused by users accessing Web pages, such as user clicks. When the user performs some operations, he executes a series of code.

Note: events are usually used in conjunction with functions, and functions are executed only when events occur.

2.2. Three ways to use events

Events are generally used to interact with browser and user operations.

There are three ways to use JavaScript: inline (inline), script and event listening;

2.2. 1. Inline mode

This model is the most traditional and simple method to deal with events. In the inline model, an event handler is an attribute of an HTML tag that handles a specified event.

Although inline was widely used in the early days, it was mixed with HTML and was not separated from HTML.

//In HTML, the event handler function is used as an attribute to execute JS code
<div id="div1" onclick="this.style.background='blue'">I am div The text inside</div>

//Execute JS function 1 as an attribute in HTML
<div id="div1" onclick="myfun1(this)">I am div The text inside</div>

<script>
    function myfun1(t){t.style.background='blue'}
</script>

Note: inline can add multiple execution functions to the same event defined by an element

<div id="div1" onclick="myfun1(),myfun2()">I am div The text inside</div>

2.2. 2. Script mode

Because the inline model violates the principle of hierarchical separation of HTML and JavaScript code. To solve this problem, we can handle events in JavaScript. This is the script model.

Get the element, add an event to it, assign a function name to the event, and remember not to add parentheses

// Get page elements
var div1 = document.getElementById("div1");

// Define event functions
function myfun1(){
  div1.style.background="blue";
}

// Bind events and their event functions to elements
div1.onclick=myfun1;

Anonymous function writing:

var div1 = document.getElementById("div1");

div1.onclick=function(){
	div1.style.background="blue";
}

 // Remove event handlers scripted
div1.onclick = null;

The corresponding code can be triggered directly through anonymous functions.

Note: multiple execution functions cannot be added to the same event in script form;

2.2. 3. Event listening (listening) mode

JavaScript defines two methods for adding events and deleting event handlers: addEventListener() and removeEventListener().

All DOM nodes contain these two methods, and they both accept three parameters; Boolean value of event type, event handler, bubble or capture (true indicates capture and false indicates bubble).

The standard browser is bound with the addEventListener function defined by W3C. The function definition is as follows:

function addEventListener(string eventType, function eventFunc, [bool useCapture=false]) parameter eventType: event name, such as click, mouseover

eventFunc: bound to the action executed in the event

useCapture: Specifies whether to bind in the capture phase. true is yes, false is no, and the default is false. ​

Note: event bubbling and capture will be discussed later!

document.addEventListener('click', function () {
  alert('document');
});

box.addEventListener('click', function () {
  alert('Lee');
});

Advantages of event listening:

1. When the same object is used When the writing method of onclick triggers multiple methods, the latter method will overwrite the previous method, that is, when the onclick event of the object occurs, only the last bound method will be executed.

If you listen with events, there will be no coverage, and each bound event will be executed. As follows:

window.onload = function(){

  var btn = document.getElementById("yuanEvent");
  btn.onclick = function(){
    alert("first event");
  }

  btn.onclick = function(){
    alert("Second event");
  }

  btn.onclick = function(){
    alert("Third event");
  }
}

Finally, only the third event is output, because the latter method overrides the previous method.

Primitive event binding function addEventListener: 
function eventOne (){
  alert("First listening event");
}

function eventTwo(){
  alert("Second listening event");
}

window.onload = function(){
  var btn = document.getElementById("yuanEvent");
  //addEventListener: binding function
  btn.addEventListener("click",eventOne);
  btn.addEventListener("click",eventTwo);
}
Output: the first listening event and the second listening event

2. After the event listening method is used to bind the object, the corresponding binding can be released. The writing method is as follows:

var eventOne = function(){
  alert("First listening event");
}
function eventTwo(){
  alert("Second listening event");
}
  var btn = document.getElementById("yuanEvent");
  btn.addEventListener("click",eventOne);
  btn.addEventListener("click",eventTwo);
  btn.removeEventListener("click",eventOne);
Output: the second listening event
 When unbinding events, you must use the handle of the function. Writing the whole function cannot unbind.

2.2. 4. IE compatible

IE9 did not support addEventListener and removeEventListener methods before;

Two similar methods are implemented:

  • attachEvent

  • detachEvent

// For the first parameter, add on before the event name
box.attachEvent('onclick', eventCode);
box.detachEvent('onclick', eventCode);

function eventCode() {
  console.log('Click to execute');
}

Both methods accept two identical parameters.

                1. Event handler name

                2. Event handler method

attachEvent -- compatible with IE7 and IE8; Incompatible with firefox, chrome, IE9, IE10, IE11, safari, opera

addEventListener -- compatible with: firefox, chrome, ie, safari, opera; Incompatible with IE7 and IE8

function addEventListener(element, type, fn) {
    if (element.addEventListener) {
        element.addEventListener(type, fn, false);
    } else if (element.attachEvent) {
        element.attachEvent('on' + type, fn);
    } else {
        element['on' + type] = fn;
    }
}

function removeEventListener(element, type, fn) {
    if (element.removeEventListener) {
        element.removeEventListener(type, fn, false);
    } else if (element.detachEvent) {
        element.detachEvent('on' + type, fn);
    } else {
        element['on' + type] = null;
    }
}

addEventListener(box, "click", function () {
    console.log("Compatibility resolution strategy")
})

2.3. Common event types

The types of events that JavaScript can handle are: mouse events, keyboard events, frame events, and form events.

All event handling functions are composed of two parts: on + event name. For example, the event handling function of click event is onclick. Here, we mainly talk about the way of script to build events. We ignore the inlining that violates the separation principle.

Mouse events:

1. click the event handle called when the user clicks an object.

2. dblclick is the event handle called when the user double clicks an object.

3. The mousedown mouse button is pressed.

4. mouseup triggers [left and right mouse buttons] when the user releases the mouse button.

5. mouseover move the mouse over an element.

6. mouseout move the mouse away from an element.

7. mousemove when the mouse is moved.

8. mouseenter is triggered when the mouse pointer moves over the element.

9. mouseleave is triggered when the mouse pointer moves out of the element

The onmouseenter event is similar to the onmouseover event. The only difference is that onmousenter events do not support bubbling.

Keyboard events:

1. keydown: when the user presses any key on the keyboard, the trigger will be repeated if it is held down.

        onkeydown = function () {alert('Lee');};

2. keypress: when the user presses the character key on the keyboard, the trigger will be repeated if it is held down.

        onkeypress = function () {alert('Lee');};

3. keyup: triggered when the user releases the key on the keyboard.

        onkeyup = function () {alert('Lee');};

Note: keyboard events are generally used on elements that can get focus or on doument objects

When a keyboard event occurs, the keyCode attribute of the keyboard event object will contain a code corresponding to a specific key on the keyboard.

Is there a difference between keypress and keydown?

        1.keydown occurs before keypress.

        2.keypress cannot system button.

        3. The keyCode captured by Keydown is not case sensitive, but keypress is.

        4.keypress occurs when the user presses and releases any alphanumeric key. System buttons (e.g. arrow keys and function keys) are not recognized.

        5.keyup occurs when the user releases any previously pressed keyboard key.

        6.keydown occurs when the user presses any keyboard key (including system buttons, such as arrow keys and function keys).

Frame/Object Events

1. load is triggered on the window after the page is fully loaded, or on the frameset after the frameset is loaded. Execute when the page is fully loaded with all content (including images, script files, CSS files, etc.)

2. The unload user exits the page. (< body > and < frameset >)

<div id="box">
    
</div>
<script>
    // Execute after the BOM onload page is loaded  
    // Page loading is completed, all elements on the page are created, and the referenced external resources are downloaded (js, css, pictures)
    // window.onload = function () {
    onload = function () {
    var box = document.getElementById('box');
    console.log(box);
    }

    // window.onunload = function () {
    // Execute when the page is unloaded
    onunload = function () {
    // In onunload, all dialog boxes cannot be used, and the window object is frozen
    // Blocked alert('Welcome to come again next time ') during unload
    // alert('Welcome to come again next time ');
    console.log('bye bye');
    }
    
    // f5 refresh page  
    // 1 uninstall page
    // 2 reload page
</script>

3. beforeunload this event is triggered when you are about to leave the page (refresh or close)

4. hashchange this event is triggered when the anchor part of the current URL is modified.

5. resize is triggered on the window or frame when the size of the window or frame changes.

6. scroll is triggered when the user scrolls.

Form events:

1. select triggered when the user selects one or more characters in the text box (input or textarea).

2. change this event is triggered when the content of the form element changes (< input >, < keygen >, < Select >, and < textarea >).

3. Triggered when the focus element obtains the focus.

4. Triggered when the blur element loses focus.

5. Submit is triggered on the < form > element when the user clicks the submit button.

6. Reset is triggered on the < form > element when the user clicks the reset button.

<form action="" onsubmit="myFun1()" onreset="myfun2()">
    <input type="text" name="userName" placeholder="Please enter your name" > <br>
    <input type="submit" value="Submit Form "><input type="reset" value="Reset Form ">
</form>
<script>
    function myFun1(){
        var userName = document.getElementsByTagName("input")[0].value;
        alert("hello,"+userName);
    }
    function myfun2(){alert("You reset the form");}
</script>

7. Triggered when the input element obtains user input

2.4 event bubbling and capture

2.4. 1. Event bubbling and capture

What is event bubbling?

Trigger a certain type of event on an object (such as click event). If the object defines a handler for this event, the event will call this handler. If the event handler is not defined or the event returns true, the event will propagate to the parent object of the object from the inside to the outside until it is processed (all similar events of the parent object will be activated), or it reaches the top level of the object hierarchy, that is, the document object (some browsers are window).

Bubbling of events: events are triggered in order from the most specific event target to the least specific event target.

Event bubble can be vividly compared to throwing a stone into the water, and the bubble will always emerge from the bottom of the water. In other words, the event will start from the innermost element and propagate upward until the document object.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            #box1 {
                width: 300px;
                height: 300px;
                background-color: red;
            }

            #box2 {
                width: 200px;
                height: 200px;
                background-color: green;
            }

            #box3 {
                width: 100px;
                height: 100px;
                background-color: blue;
            }
        </style>
    </head>
    <body>
        <div id="box1">
            <div id="box2">
                <div id="box3">
                </div>
            </div>
        </div>
        <script>
            // Function of the third parameter of addEventListener
            var box1 = document.getElementById('box1');
            var box2 = document.getElementById('box2');
            var box3 = document.getElementById('box3');

            var array = [box1, box2, box3];

            // When the third parameter of addEventListener is false: event bubbling
            // When the third parameter of addEventListener is true: event capture

            for (var i = 0; i < array.length; i++) {
                array[i].addEventListener('click', function () {
                    console.log(this.id);
                }, false);
            }

            document.body.addEventListener('click', function () {
                console.log('body');
            }, false);
        </script> 
    </body>
</html>

Event capture: in contrast to event bubbling, events occur from the outermost layer to the most specific element.

During event capture, the parent element is triggered first and the child element is triggered later.

You can choose whether to use event capture or event bubbling when binding events. The method is to use the addEventListener function when binding events. It has three parameters. If the third parameter is true, it means to use event capture; if false, it means to use event bubbling.

Previous versions of IE9 only support event bubbling and do not support event capture. It also does not support the addEventListener function. It does not use the third parameter to indicate whether it is bubbling or capturing. It provides another function attachEvent.

2.4. 2. Three stages of the event

The event processing process mainly has three stages: capture stage, target stage and bubbling stage;

Capture Phase: when we perform some operations (such as clicking or moving the mouse) on a node of the DOM tree, an event will be emitted. This event will be sent from the Window and continue to pass through the subordinate nodes until the triggered target node. The process before reaching the target node is the Capture Phase (Capture Phase). Events are received by page elements, level by level down to specific elements.

Target stage: when the event is continuously transmitted to the target node, and the event is finally triggered on the target node, it is the target stage. The specific element itself.

Bubbling stage: event bubbling means that when an event starts, it is received by the most specific element (that is, the node where the event occurs), and then propagated level by level to the less specific node. Contrary to capture, the specific element itself goes up level by level to the page element (the event binding we usually use is based on the principle of event bubbling).

W3C: when any event occurs, first capture the event from the top level until the event trigger reaches the event source, and then capture the event from the event source upward (event bubbling).

Event object The eventPhase property allows you to view the phase in which the event was triggered

2.4. 3. Properties and methods of event objects (core)

In standard DOM events, the event object contains properties and methods related to the specific event that created it. The event object represents the state of the event, such as the element in which the event occurs, the state of keyboard keys, the position of the mouse, and the state of mouse buttons.

When will an Event object be generated?  
Event object, which is generally called event object, is passed by the browser as a parameter through a function. Through the event bound execution function, you can get a hidden parameter, which is actually an event object.

Events are usually used in conjunction with functions. Functions will not be executed before the event occurs!

var oDIv = document.getElementById('box');

oDiv.onclick = function(event){
    .........
}
  • event.eventPhase returns the current stage of event propagation.

  • event. target || event. Srclelement returns the element that triggered this event (the target node of the event).

  • event.currentTarget returns the element whose event listener triggered the event

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    #box1 {
      width: 300px;
      height: 300px;
      background-color: red;
    }

    #box2 {
      width: 200px;
      height: 200px;
      background-color: green;
    }

    #box3 {
      width: 100px;
      height: 100px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <input type="button" value="Button" id="btn">
  <div id="box1">
    <div id="box2">
      <div id="box3">
      </div>
    </div>
  </div>
  <script>
    // Through the event object, you can get some data related to the event when the event occurs
    var btn = document.getElementById('btn');
    btn.onclick = function (e) {
      // In the DOM standard, an event handler is given a parameter
      // e is the event object
      // The way to get the event object in the old version of IE is window event
      // Browser compatibility for handling event objects
      e = e || window.event;

      // Phase of the event: 1 capture phase 2 target phase 3 bubble phase understanding
      // console.log(e.eventPhase);

      // e.target gets the object browser compatibility problem that really triggers the event
      // Srclelement in older versions of IE
      // Handling compatibility issues
      var target = e.target || e.srcElement;
      console.log(e.target);
        
      // e. this object to which the currenttarget event handler belongs
      console.log(e.currentTarget);
    }

    var box1 = document.getElementById('box1');
    var box2 = document.getElementById('box2');
    var box3 = document.getElementById('box3');
    var array = [box1, box2, box3];
    for (var i = 0; i < array.length; i++) {
      var box = array[i];
      box.onclick = function (e) {
        e = e || window.event;
        // Phase of the event
        console.log(e.eventPhase);
        // e.target gets the object that actually triggers the event
        var target = e.target || e.srcElement;
        console.log(target);
        // e. Like this, currenttarget gets the object to which the event handler belongs
        console.log(e.currentTarget);
        console.log(this);
      }
    }
  </script>
</body>

</html>
  • event.bubbles returns a boolean indicating whether the event is a bubbling event type

  • event.cancelable returns a Boolean value indicating whether the event can have a cancelable default action.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    #box1 {
      width: 300px;
      height: 300px;
      background-color: red;
    }

    #box2 {
      width: 200px;
      height: 200px;
      background-color: green;
    }

    #box3 {
      width: 100px;
      height: 100px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <input type="button" value="Button" id="btn">
  <div id="box1">
    <div id="box2">
      <div id="box3">
      </div>
    </div>
  </div>

  <input type="text" id="input1">
  <script>
    var box1 = document.getElementById('box1');
    var box2 = document.getElementById('box2');
    var box3 = document.getElementById('box3');
    var input1 = document.getElementById('input1');
    var array = [box1, box2, box3];
    for (var i = 0; i < array.length; i++) {
      var box = array[i];
      //Bubble event types: click, mousedown, mouseup, keydown, keyup, keypress, etc
      box.onclick = function (e) {
        e = e || window.event;
        console.log(e);
        // Is it a bubbling event type
        console.log(e.bubbles);
        // Can I cancel the default action
        console.log(e.cancelable);
      }

    }

    input1.onfocus = function (e) {
      e = e || window.event;
      // Is it a bubbling event type
      console.log(e.bubbles);
      // Can I cancel the default action
      console.log(e.cancelable);
    }
  </script>
</body>

</html>
  • event.type gets the event type

  • event.timeStamp returns the date and time when the event was generated.

var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var box3 = document.getElementById('box3');
var input1 = document.getElementById('input1');
var array = [box1, box2, box3];
for (var i = 0; i < array.length; i++) {
    var box = array[i];
    //Bubble event types: click, mousedown, mouseup, keydown, keyup, keypress, etc
    box.onclick = function (e) {
        e = e || window.event;
        // Get event type
        console.log(e.type);
        //   Returns the date and time when the event was generated.
        console.log(e.timeStamp)
    }

}

input1.onfocus = function (e) {
    e = e || window.event;
    // Get event type
    console.log(e.type);
    //   Returns the date and time when the event was generated.
    console.log(e.timeStamp)
}

// Get time type: you can bind an event function to multiple events to improve performance
var box = document.getElementById('box');
// box.onclick = function (e) {
//   e = e || window.event;
//   //Get event name
//   console.log(e.type);
// }

box.onclick = fn;
box.onmouseover = fn;
box.onmouseout = fn;

function fn(e) {
    e = e || window.event;
    switch (e.type) {
        case 'click': 
            console.log('click box');
            break;
        case 'mouseover': 
            console.log('Mouse passing box');
            break;
        case 'mouseout': 
            console.log('Mouse away box');
            break;
    }
}
  • event.clientX/clientY is supported by all browsers, and the window position

  • event.pageX/pageY IE9 was not supported before, page position

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      height: 1000px;
    }
    #box {
      margin: 100px;
      margin-top: 500px;
      width: 200px;
      height: 200px;
      background-color: red;
    }
  </style>
</head>
<body>
  <div id="box">
  </div> 
  <script>
    var box = document.getElementById('box');
    box.onclick = function (e) {
      e = e || window.event;

      // Gets the coordinates of the mouse in the visible area of the browser
      // console.log(e.clientX);
      // console.log(e.clientY);

      // Position of the mouse on the current page
      console.log(e.pageX);
      console.log(e.pageY);

    }

  </script>
</body>
</html>

pageX and pageY compatibility solution

e.clientX/e.clientY mouse position in the visual area

The position of e.pageX/e.pageY mouse in the page has compatibility problems. It is only supported after IE9

pageY = clientY + the distance the page scrolls out

Step 1: get the page scrolling distance

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    body {
      height: 1000px;
    }

    div {
      width: 300px;
      height: 300px;
      background: yellow;
      margin-top: 360px;
    }
  </style>
</head>

<body>
  <div>

  </div>
  <script>
    document.onclick = function () {
      // Output page scrolling distance
      console.log(document.body.scrollLeft);
      console.log(document.body.scrollTop);

      // documentElement the html tag of the root element of the document
      // console.log(document.documentElement);
      // Some browsers use these two properties to get
      console.log(document.documentElement.scrollLeft);
      console.log(document.documentElement.scrollTop);

    }

    // Browser compatibility problem of getting page scrolling distance
    // Gets the distance the page scrolls out
    function getScroll() {
      var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
      var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
      return {
        scrollLeft: scrollLeft,
        scrollTop: scrollTop
      }
    }
  </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    body {
      height: 1000px;
    }
  </style>
</head>

<body>

  <script>
    // e.clientX/e.clientY mouse position in the visible area
    // e. The position of pagex / e.pagey mouse in the page has compatibility problems. It is only supported after IE9
    // pageY = clientY + the distance the page scrolls out
    document.onclick = function (e) {
      e = e || window.event;
      console.log(getPage(e).pageX);
      console.log(getPage(e).pageY);

    }

    // Get the position of the mouse on the page and deal with browser compatibility
    function getPage(e) {
      var pageX = e.pageX || e.clientX + getScroll().scrollLeft;
      var pageY = e.pageY || e.clientY + getScroll().scrollTop;
      return {
        pageX: pageX,
        pageY: pageY
      }
    }

    // Browser compatibility problem of getting page scrolling distance
    // Gets the distance the page scrolls out
    function getScroll() {
      var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
      var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
      return {
        scrollLeft: scrollLeft,
        scrollTop: scrollTop
      }
    }
  </script>
</body>

</html>
  • Modify key

Sometimes, we need some keys on the keyboard to cooperate with the mouse to trigger some special events. These keys are: Shfit, Ctrl and Alt. they are often used to modify mouse events and behaviors, so they are called modify keys.

Attribute description

shiftKey: judge whether the Shfit key is pressed

CTRL key determines whether the CTRL key is pressed

altKey: determine whether the alt key is pressed

1. Judge whether to press alt key, shift key and ctrl key

document.onkeydown = function (e) {
    if(e.altKey){
        alert("alt Press");
    }else if(e.shiftKey){
        alert("shift Press");
    }else if(e.ctrlKey){
        alert("ctrl Press");
    }else{
        alert("Not pressed alt/shift/ctrl");
    }
}

2. Judge whether alt key, shift key and ctrl key are pressed at the same time

document.onkeydown = function (e) {
    if(e.altKey && e.shiftKey ){
        alert("Press simultaneously");
    }
}


document.onkeydown = function (e) {
    if(e.altKey && e.shiftKey && e.ctrlKey){
        alert("Press simultaneously");
    }
}
  • Key code

When keydown and keyup events occur, the keyCode attribute of the event object will contain a code corresponding to a specific key on the keyboard. For alphanumeric character sets, the value of the keyCode attribute is the same as the encoding of the corresponding lowercase letters or numbers in ASCII code. Case in letters does not affect.

document.onkeydown = function (evt) {
	alert(evt.keyCode); //Press any key to get the corresponding keyCode
};

// Each key on the keyboard has a keyCode. You can obtain the keyCode corresponding to each key by the following methods.
document.onkeydown = function (e) {
   alert(e.keyCode);
}

document.onkeypress = function (e) {
   alert(e.keyCode);
}

The event objects of Firefox, Chrome and Safari all support a charCode attribute. This attribute contains a value only when the keypress event occurs, and this value is the ASCII encoding of the character represented by the key pressed. At this time, the keyCode is usually equal to 0 or may also be equal to the code of the key. IE and Opera are ASCII codes that store characters in keyCode.

document.onkeypress = function (e) {
   var key = String.fromCharCode(e.charCode);
    alert(key);
}

Note that you can use string Fromcharcode() converts ASCII encoding to actual characters.

2.4. 4. Event delegation

What is event delegation?

In terms of JavaScript advanced programming, event delegation is to use event bubbling and specify only one event handler to manage all events of a certain type.

give an example:

Three colleagues are expected to receive the express on Monday. There are two ways to sign for express delivery: first, three people wait for express delivery at the door of the company; The second is to entrust the front desk MM to sign for it. In reality, Most of us adopt the entrusted scheme (the company will not tolerate so many employees standing at the door to wait for the express). After receiving the express, the front desk MM will judge who the recipient is, sign for it according to the recipient's requirements, and even pay for it. This scheme has another advantage, that is, even if new employees come to the company (no matter how much), the front desk MM will also verify and sign for the new employee after receiving the express.

There are actually two meanings here:

First, the colleague at the front desk can sign in on behalf of others, that is, the existing dom node in the program has events;

Second, new employees can also be signed in by the foreground MM, that is, the newly added dom node in the program also has events.

Why use event delegation?

Generally speaking, dom needs event handlers. We will directly set event handlers for it. What if many DOMS need to add event handlers? For example, we have 100 li, and each li has the same click event. Maybe we will use the for loop method to traverse all li, and then add events to them. What impact will this have?

In JavaScript, the number of event handlers added to the page will directly affect the overall running performance of the page, because it needs to constantly interact with DOM nodes. The more times you visit DOM, the more times the browser redraws and rearranges, which will prolong the interaction readiness time of the whole page, This is why one of the main ideas of performance optimization is to reduce DOM operations; If event delegation is used, all operations will be put into the js program, and the operations with DOM only need to interact once, which can greatly reduce the number of interactions with Dom and improve performance;

Each function is an object, which will occupy memory. The more objects, the greater the memory occupancy rate, and the worse the natural performance. For example, the 100 li above will occupy 100 memory space. If it is 1000 or 10000, it can only be said that if you use event delegation, Then we can only operate on its parent (if there is only one parent). In this way, we need a memory space. Does it save a lot and the natural performance will be better.

Principle of event delegation:

Event delegation is implemented by using the bubble principle of events

How to implement event delegation:

<ul id="ul1">
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>

The implementation function is to click li to pop up 123:

window.onload = function(){
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    for(var i=0;i<aLi.length;i++){
        aLi[i].onclick = function(){
            alert(123);
        }
    }
}

The meaning of the above code is very simple. I believe many people implement it in this way. Let's see how many dom operations there are. First, find the ul, then traverse the li, and then click the li, and then find the location of the target li once to perform the final operation. Each click must find the li;

So what happens if we use event delegation?

window.onload = function(){
    var oUl = document.getElementById("ul1");
   oUl.onclick = function(){
        alert(123);
    }
}

Here, the parent ul is used for event processing. When li is clicked, due to the bubble principle, the event will bubble on the ul. Because there is a click event on the ul, the event will be triggered. Of course, when ul is clicked, it will also be triggered. Then the problem arises. What if I want the effect of the event agent to be the same as that directly given to the node, For example, it can only be triggered by clicking li. We are not afraid. We have unique skills:

The Event object provides an attribute called target, which can return the target node of the Event. We become the Event source, that is, the target can be expressed as the dom of the current Event operation, but it is not the real DOM operation. Of course, this is compatible. EV is used for standard browsers Target, IE browser Event Srclelement, at this time, only gets the location of the current node and does not know what the node name is. Here, we use nodeName to get the specific tag name. This returns an uppercase, which we need to convert to lowercase for comparison (habit problem):

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
       // Check whether the event source e.target is Li 
    if(target.nodeName.toLowerCase() == 'li'){
         alert(123);
         alert(target.innerHTML);
    }
  }
}

In this way, only clicking li will trigger events, and dom operations will be executed only once at a time. If there are a large number of li, dom operations will be greatly reduced, and the optimized performance can be imagined!

The above example shows that li operates with the same effect. If the effect of each li click is different, is it still useful to use event delegation?

<div id="box">
    <input type="button" id="add" value="add to" />
    <input type="button" id="remove" value="delete" />
    <input type="button" id="move" value="move" />
    <input type="button" id="select" value="choice" />
</div>
window.onload = function(){
    var Add = document.getElementById("add");
    var Remove = document.getElementById("remove");
    var Move = document.getElementById("move");
    var Select = document.getElementById("select");

    Add.onclick = function(){
        alert('add to');
    };
    Remove.onclick = function(){
        alert('delete');
    };
    Move.onclick = function(){
        alert('move');
    };
    Select.onclick = function(){
        alert('choice');
    }

}

I won't say much about the effect achieved above. It's very simple. If you click each of the four buttons to do different operations, you need at least four dom operations. If you use event delegation, can you optimize it?

window.onload = function(){
    var oBox = document.getElementById("box");
    oBox.onclick = function (ev) {
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if(target.nodeName.toLocaleLowerCase() == 'input'){
            switch(target.id){
                case 'add' :
                    alert('add to');
                    break;
                case 'remove' :
                    alert('delete');
                    break;
                case 'move' :
                    alert('move');
                    break;
                case 'select' :
                    alert('choice');
                    break;
            }
        }
    }

}

With event delegation, you can complete all the effects with only one dom operation, which is certainly better than the above performance

Now we are talking about the operations under the existing dom node after document loading. If it is a new node, will there be an event on the new node? In other words, when a new employee comes, can he receive the express?

Take a look at the normal method of adding nodes:

<input type="button" name="" id="btn" value="add to" />
<ul id="ul1">
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>

Now move in li, li turns red, move out li, li turns white. Then click the button to add a li child node to the ul

window.onload = function(){
    var oBtn = document.getElementById("btn");
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    var num = 4;

    //The mouse turns red when moving in and white when moving out
    for(var i=0; i<aLi.length;i++){
        aLi[i].onmouseover = function(){
            this.style.background = 'red';
        };
        aLi[i].onmouseout = function(){
            this.style.background = '#fff';
        }
    }
    //Add new node
    oBtn.onclick = function(){
        num++;
        var oLi = document.createElement('li');
        oLi.innerHTML = 111*num;
        oUl.appendChild(oLi);
    };
}

This is a common practice, but you will find that the new li has no events. It means that when adding child nodes, the events are not added together. This is not the result we want. What should we do? The general solution is to wrap the for loop with a function named mhiver, as follows:

window.onload = function(){
    var oBtn = document.getElementById("btn");
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    var num = 4;

    function mHover () {
        //The mouse turns red when moving in and white when moving out
        for(var i=0; i<aLi.length;i++){
            aLi[i].onmouseover = function(){
                this.style.background = 'red';
            };
            aLi[i].onmouseout = function(){
                this.style.background = '#fff';
            }
        }
    }
    mHover ();
    //Add new node
    oBtn.onclick = function(){
        num++;
        var oLi = document.createElement('li');
        oLi.innerHTML = 111*num;
        oUl.appendChild(oLi);
        mHover ();
    };
}

Although the function has been implemented, it looks good, but in fact, there is no doubt that another dom operation has been added, which is not desirable in terms of optimizing performance. Can the event delegation be optimized?

window.onload = function(){
    var oBtn = document.getElementById("btn");
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    var num = 4;

    //Event delegate, and the added child element also has events
    oUl.onmouseover = function(ev){
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if(target.nodeName.toLowerCase() == 'li'){
            target.style.background = "red";
        }

    };
    oUl.onmouseout = function(ev){
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if(target.nodeName.toLowerCase() == 'li'){
            target.style.background = "#fff";
        }

    };

    //Add new node
    oBtn.onclick = function(){
        num++;
        var oLi = document.createElement('li');
        oLi.innerHTML = 111*num;
        oUl.appendChild(oLi);
    };
}

Look, the above method uses event delegation. The newly added child elements have event effects. We can find that when using event delegation, you don't need to traverse the child nodes of the element at all. You just need to add events to the parent element. Everything else is executed in js, which can greatly reduce dom operations, This is the essence of event delegation.

Events suitable for event delegation: click, mousedown, mouseup, keydown, keyup, keypress.

It is worth noting that although mouseover and mouseout also have event bubbles, they need special attention when dealing with them, because their positions need to be calculated frequently, which is not easy to deal with.

There are many unsuitable ones. For example, mousemove has to calculate its position every time. It's very difficult to control. For example, focus, blur and so on, they don't use the bubbling feature. Naturally, they can't use event delegation.

2.4. 5. Block event

        event. The stoppropagation () method prevents the event from continuing to propagate in the DOM and from triggering the listening functions defined on other nodes, but does not include other event listening functions on the current node.

function stopEvent(e) {
  // Standard DOM method
  e.stopPropagation();
    
  // Cancel bubbling non-standard way, old version of IE support
  e.cancelBubble = true;
}

el.addEventListener('click', stopEvent, false);

In the above code, the click event will not bubble further to the parent node of the el node.

//Compatible writing to prevent event bubbling
function stopBubble(e){
    //If an event object is provided, it is a non IE browser
    if(e && e.stopPropagation)
        //Therefore, it supports W3C's stopPropagation() method
        e.stopPropagation();
    else
        //Otherwise, we need to use IE to cancel event bubbling
        window.event.cancelBubble = true;
}

        event. The preventdefault () method cancels the browser's default behavior for the current event. This is a method to block the default event. When this method is called, the connection will not be opened, but bubbles will occur, and the bubbles will be passed to the parent element of the previous layer;

For example, after clicking the link, the browser will jump to another page by default. After using this method, it will not jump;

The precondition for this method to take effect is that the cancelable attribute of the event object is true. If it is false, calling this method has no effect.

A method to prevent event bubbling, where e is a parameter in function;

<input type="checkbox" id="my-checkbox" />

<script>
    var cb = document.getElementById('my-checkbox');
    cb.addEventListener(
        'click',
        function (e) {
            // DOM standard method
            e.preventDefault();

            // Old version of IE, non-standard way
      		e.returnValue = false;
        },
        false
    );
</script>

In the above code, the default behavior of the browser is to click to select the radio box. If you cancel this behavior, the radio box cannot be selected.

return false, this method will also block the default event;

<div id="div1">
    <a href="http://www.baidu. Com "id =" Mya "> I'm a hyperlink</a>
</div>

<script>
    var myA = document.getElementById('myA');
    var div1 = document.getElementById("div1");
    div1.onclick = function () {
        alert("div1 Event triggered");
    }

    myA.onclick = function () {
        return false;
    }
</script>
//Prevent compatible writing of the default behavior of events
function stopDefault(e){
    //If an event object is provided, it is a non IE browser
    if(e && e.preventDefault)
        //Therefore, it supports W3C's preventDefault() method
        e.preventDefault();
    else
        //Otherwise, we need to use IE to cancel the default behavior of events
        window.event.returnValue = false;
}

2.5 event flow

A long time ago, there was a girl named Netscape, She developed a set of event driven mechanism (i.e. event Capture) for Javascript. Later, a boy named "IE" was arrogant. He thought "why should I follow your rules", so he created a set of his own rules (event bubbling). Later, a matchmaker named W3C wanted to bring the two children together and integrate their characteristics. The sequence of events was as follows: events were sent from the root node to the child node level by level. If the node was bound with an event action, it performed the action and then continued. This stage is called "capture"; After the capture phase is executed, the event is sent from the child node to the root node. If the node is bound with an event action, execute the action and then continue. This phase is called "bubble".

Event flow describes the sequence of receiving events from the page. When several elements with the same event are stacked together, such as clicking an event, when you click one of the elements, not only the currently clicked element will trigger the event, but all elements stacked in your click range will trigger the event. Event flow includes two modes: bubbling and capture (capture).

Event bubbling is triggered one by one from the inside out. Event capture is triggered one by one from the outside to the inside. Then modern browsers are bubble model by default, while capture mode is the default of early Netscape.

When we perform some operations on a node of the DOM tree (for example, click or move the mouse), an event will be emitted. This event will be sent from the Window and continue to pass through the lower node to the target node. The process before reaching the target node is the Capture Phase (Capture Phase). All passing nodes will trigger this event. The task of the Capture Phase is to establish this event transmission route so that the subsequent bubble phase can return to Window along this route.

To listen to an event triggered in the capture phase, you need to pass the third parameter true in the event listening function.

Topics: Javascript Front-end ECMAScript