Other common events

Resource Events

beforeunload event

The beforeunload event is triggered before windows, documents, and various resources are about to be unloaded. It can be used to prevent users from accidentally uninstalling resources.

If the returnValue property of the event object is a non-empty string, the browser will pop up a dialog box asking the user whether to uninstall the resource. However, the character string specified by the user may not be displayed, and the browser will display a predefined character string. If the user clicks the "Cancel" button, the resource will not be uninstalled.

window.addEventListener("beforeunload", function (event) {
  event.returnValue = "Are you sure to leave? ";
});

In the above code, if the user closes the window, the browser will pop up a window asking the user to confirm.

The behavior of browsers on this event is very inconsistent. Some browsers call event.preventDefault(), and a dialog box will pop up. The IE browser needs to explicitly return a non-empty string before the dialog box will pop up. Moreover, most browsers do not display the specified text in the dialog box, only the default text. Therefore, you can use the following wording to achieve maximum compatibility.

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "Are you sure to close the window? ";

  e.returnValue = confirmationMessage;
  return confirmationMessage;
});

Note that many mobile browsers (such as Safari) ignore this event by default, and desktop browsers also have ways to ignore this event. Therefore, it may not take effect at all, and you cannot rely on it to prevent the user from closing the browser window. It is best not to use this event.

In addition, once the beforeunload event is used, the browser will not cache the current webpage, and using the "back" button will request the webpage from the server again. This is because the purpose of monitoring this event is generally for the state of the web page. At this time, caching the initial state of the page is meaningless.

unload event

The unload event is triggered when the window is closed or the document object is about to be unloaded. Its trigger sequence is after the beforeunload and pagehide events.

When the unload event occurs, the document is in a special state. All resources still exist, but they are not visible to the user, and all UI interactions are invalid. This event cannot be cancelled. Even if an error is thrown in the listener function, the unloading of the document cannot be stopped.

window.addEventListener("unload", function (event) {
  console.log("Document will be uninstalled");
});

On the mobile phone, the browser or the system may directly discard the web page, at this time the event will not happen at all. And like the beforeunload event, once the unload event is used, the browser will not cache the current web page for the same reason as above. Therefore, this event should not be relied on under any circumstances. Specify the code to be executed when the web page is uninstalled. You can consider not using this event at all.

This event can be replaced by pagehide.

load event, error event

The load event is triggered when the page or a resource is successfully loaded. Note that the page or resource is loaded from the browser cache and will not trigger the load event.

window.addEventListener("load", function (event) {
  console.log("All resources have been loaded");
});

The error event is triggered when a page or resource fails to load. The abort event is triggered when the user cancels the loading.

These three events are actually progress events, which not only occur on the document object, but also on various external resources. Browsing the web is a process of loading various resources, such as images, style sheets, scripts, videos, audios, Ajax requests (XMLHttpRequest), and so on. These resources, the document object, the window object, and the XMLHttpRequestUpload object all trigger the load event and the error event.

Finally, the load event of the page can also be replaced by the pageshow event.

session historical events

pageshow event, pagehide event

By default, the browser will cache the page in the current session. When the user clicks the "forward/back" button, the browser will load the page from the cache.

The pageshow event is triggered when the page is loaded, including the first load and the load from the cache. If you want to specify the code that runs every time the page is loaded (whether it is cached from the browser), you can put it in the listener function of this event.

When it is loaded for the first time, its trigger sequence is after the load event. When loading from the cache, the load event will not be triggered, because the web page in the cache is usually the way the listener function of the load event runs, so there is no need to repeat the execution. Similarly, if the page is loaded from the cache, the JavaScript scripts initialized in the page (such as the listener function for the DOMContentLoaded event) will not be executed.

window.addEventListener("pageshow", function (event) {
  console.log("pageshow:", event);
});

The pageshow event has a persisted property, which returns a boolean value. When the page is loaded for the first time, this attribute is false; when the page is loaded from the cache, this attribute is true.

window.addEventListener("pageshow", function (event) {
  if (event.persisted) {
    // ...
  }
});

The pagehide event is similar to the pageshow event, which is triggered when the user leaves the current page through the "forward/back" button. The difference between it and the unload event is that if the listener function of the unload event is defined on the window object, the page will not be saved in the cache, but if the pagehide event is used, the page will be saved in the cache.

The pagehide event instance also has a persisted property. Setting this property to true means that the page is to be stored in the cache; setting it to false means that the web page is not stored in the cache. At this time, if unload is set Event monitoring function, this function will run immediately after the pagehide event.

If the page contains <frame> or <iframe> elements, the pageshow event and pagehide event of the <frame> page will both be triggered before the main page.

Note that these two events are only triggered when the browser's history object changes, and it has nothing to do with whether the web page is visible.

popstate event

The popstate event is triggered when the current record of the browser's history object is explicitly switched. Note that calling history.pushState() or history.replaceState() will not trigger the popstate event. This event is only triggered when the user explicitly switches between history records, such as clicking the "back/forward" button with the mouse, or calling history.back(), history.forward(), in a script Triggered when history.go().

The event object has a state property, which saves the state object added by the history.pushState method and the history.replaceState method to the current record.

window.onpopstate = function (event) {
  console.log("state: " + event.state);
};
history.pushState({ page: 1 }, "title 1", "?page=1");
history.pushState({ page: 2 }, "title 2", "?page=2");
history.replaceState({ page: 3 }, "title 3", "?page=3");
history.back(); // state: {"page":1}
history.back(); // state: null
history.go(2); // state: {"page":3}

In the above code, the pushState method adds two records to the history, and then the replaceState method replaces the current record. Therefore, two consecutive back methods will make the current entry return to the original URL. It does not have a state object attached, so the state property of the event is null, and then two records are forwarded and returned to replaceState. The record added by the method.

Whether the browser triggers the popstate event for the first time the page loads, the handling is different, and Firefox does not trigger the event.

hashchange event

The hashchange event is triggered when the hash part of the URL (that is, the part after the #, including the #) changes. This event is generally monitored on the window object.

The event instance of hashchange has two unique attributes: the oldURL attribute and the newURL attribute, which respectively represent the complete URL before and after the change.

// URL is http://www.example.com/
window.addEventListener("hashchange", myFunction);

function myFunction(e) {
  console.log(e.oldURL);
  console.log(e.newURL);
}

location.hash = "part2";
// http://www.example.com/
// http://www.example.com/#part2

Webpage status event

DOMContentLoaded event

After the web page is downloaded and parsed, the browser will trigger the DOMContentLoaded event on the document object. At this time, only the parsing of the web page is completed (the DOM of the entire page is generated), and all external resources (style sheets, scripts, iframes, etc.) may not be downloaded yet. In other words, this event occurred much earlier than the load event.

document.addEventListener("DOMContentLoaded", function (event) {
  console.log("DOM generation");
});

Note that the JavaScript script of the web page is executed synchronously. Once the script is blocked, the triggering of the DOMContentLoaded event will be delayed.

document.addEventListener("DOMContentLoaded", function (event) {
  console.log("DOM generation");
});

// This code will delay triggering the DOMContentLoaded event
for (var i = 0; i < 1000000000; i++) {
  // ...
}

readystatechange event

The readystatechange event is triggered when the readyState property of the Document object and the XMLHttpRequest object changes. document.readyState has three possible values: loading (the webpage is loading), interactive (the webpage has been parsed, but the external resources are still in the loading state), and complete (the webpage and all external resources are finished) Load, the load event is about to fire).

document.onreadystatechange = function () {
  if (document.readyState === "interactive") {
    // ...
  }
};

This event can be seen as another implementation method of the DOMContentLoaded event.

Window event

scroll event

The scroll event is triggered when the document or document element is scrolled, mainly when the user drags the scroll bar.

window.addEventListener("scroll", callback);

This event will be triggered continuously in large numbers, so there should not be a very computationally intensive operation in its listener function. The recommended approach is to use requestAnimationFrame or setTimeout to control the trigger frequency of the event, and then combine with customEvent to throw a new event.

(function () {
  var throttle = function (type, name, obj) {
    var obj = obj || window;
    var running = false;
    var func = function () {
      if (running) {
        return;
      }
      running = true;
      requestAnimationFrame(function () {
        obj.dispatchEvent(new CustomEvent(name));
        running = false;
      });
    };
    obj.addEventListener(type, func);
  };

  // Turn the scroll event into an optimizedScroll event
  throttle("scroll", "optimizedScroll");
})();

window.addEventListener("optimizedScroll", function () {
  console.log("Resource conscious scroll callback!");
});

In the above code, the throttle() function is used to control the frequency of event triggering. It has an internal function func(), which is actually triggered each time the scroll event. The func() function uses the requestAnimationFrame() method internally to ensure that the optimizedScroll event may only be triggered every time the page is redrawn (60 times per second), thereby actually converting the scroll event to The optimizedScroll event, the trigger frequency is controlled at most 60 times per second.

Use the setTimeout() method instead to place a larger time interval.

(function () {
  window.addEventListener("scroll", scrollThrottler, false);

  var scrollTimeout;
  function scrollThrottler() {
    if (!scrollTimeout) {
      scrollTimeout = setTimeout(function () {
        scrollTimeout = null;
        actualScrollHandler();
      }, 66);
    }
  }

  function actualScrollHandler() {
    // ...
  }
})();

In the above code, the scrollThrottler function will be executed every time the scroll event. There is a timer setTimeout in this function, which triggers the actual task actualScrollHandler every 66 milliseconds (15 times per second).

The following is a more general way of writing the throttle function.

function throttle(fn, wait) {
  var time = Date.now();
  return function () {
    if (time + wait - Date.now() < 0) {
      fn();
      time = Date.now();
    }
  };
}

window.addEventListener("scroll", throttle(callback, 1000));

The above code limits the trigger frequency of the scroll event to once per second.

The lodash library provides ready-made throttle functions that can be used directly.

window.addEventListener("scroll", _.throttle(callback, 1000));

The concept of debounce was introduced earlier in this book. The difference between throttle and it is that throttle is "throttling", ensuring that it is executed only once in a period of time, while debounce is "anti-shake", and the continuous operation must be ended Perform it later. Taking webpage scrolling as an example, debounce will not be executed until the user stops scrolling, and throttle means that if the user has been scrolling the webpage, it will still be executed during the scrolling process.

resize event

The resize event is triggered when the browser window size is changed, and it mainly occurs on the window object.

var resizeMethod = function () {
  if (document.body.clientWidth < 768) {
    console.log("Viewport of mobile device");
  }
};

window.addEventListener("resize", resizeMethod, true);

This event will also be triggered continuously in large numbers, so it is best to control the frequency of event triggering through the throttle function like the scroll event above.

fullscreenchange event, fullscreenerror event

The fullscreenchange event is triggered when entering or exiting the full screen state. This event occurs on the document object.

document.addEventListener("fullscreenchange", function (event) {
  console.log(document.fullscreenElement);
});

The fullscreenerror event is triggered when the browser cannot switch to the full screen state.

Clipboard events

The following three events are related to clipboard operations.

-cut: Remove the selected content from the document and trigger when it is added to the clipboard. -copy: Triggered when the copy action is performed. -paste: Triggered after the clipboard content is pasted into the document.

For example, if you want to disable the paste event of the input box, you can use the following code.

inputElement.addEventListener("paste", (e) => e.preventDefault());

The above code makes it impossible for the user to paste content in the <input> input box.

The event objects of the three events cut, copy, and paste are all instances of the ClipboardEvent interface. ClipboardEvent has an instance property clipboardData, which is a DataTransfer object, which stores the cut and paste data. For the specific API interface and operation method, please refer to the DataTransfer object part of "Drag Event".

document.addEventListener("copy", function (e) {
  e.clipboardData.setData("text/plain", "Hello, world!");
  e.clipboardData.setData("text/html", "<b>Hello, world!</b>");
  e.preventDefault();
});

The above code makes the data copied into the clipboard is the data specified by the developer, not the data that the user wants to copy.

Focus event

Focus events occur on element nodes and document objects, and are related to gaining or losing focus. It mainly includes the following four events.

-focus: Triggered after the element node gets the focus, the event will not bubble. -blur: Triggered when the element node loses focus, the event will not bubble. -focusin: Triggered when the element node is about to gain focus, before the focus event. The event will bubble up. -focusout: Triggered when the element node is about to lose focus, before the blur event. The event will bubble up.

The event objects of these four events all inherit the FocusEvent interface. The FocusEvent instance has the following properties.

-FocusEvent.target: The target node of the event. -FocusEvent.relatedTarget: For the focusin event, return the node that lost focus; for the focusout event, return the node that will receive the focus; for the focus and blur events, return null.

Since the focus and blur events do not bubble and can only be triggered during the capture phase, the third parameter of the addEventListener method needs to be set to true.

form.addEventListener(
  "focus",
  function (event) {
    event.target.style.background = "pink";
  },
  true
);

form.addEventListener(
  "blur",
  function (event) {
    event.target.style.background = "";
  },
  true
);

The above code is for the text input box of the form. It sets the background color when the focus is accepted, and removes the background color when the focus is lost.

CustomEvent interface

The CustomEvent interface is used to generate custom event instances. Although the events predefined by the browser can be generated manually, it is often impossible to bind data to the event. If you need to pass in the specified data while triggering the event, you can use the custom event object generated by the CustomEvent interface.

The browser natively provides the CustomEvent() constructor to generate CustomEvent event instances.

new CustomEvent(type, options);

The CustomEvent() constructor accepts two parameters. The first parameter is a string, which represents the name of the event, which is required. The second parameter is the configuration object of the event, this parameter is optional. The configuration object of CustomEvent has only one property of its own in addition to the configuration properties of the Event event.

-detail: indicates the incidental data of the event, the default is null.

Below is an example.

var event = new CustomEvent("build", { detail: "hello" });

function eventHandler(e) {
  console.log(e.detail);
}

document.body.addEventListener("build", function (e) {
  console.log(e.detail);
});

document.body.dispatchEvent(event);

In the above code, we manually defined the build event. After the event is triggered, it will be monitored and output the detail property of the event instance (ie the string hello).

Here is another example.

var myEvent = new CustomEvent("myevent", {
  detail: {
    foo: "bar",
  },
  bubbles: true,
  cancelable: false,
});

el.addEventListener("myevent", function (event) {
  console.log("Hello " + event.detail.foo);
});

el.dispatchEvent(myEvent);

The above code also shows that, in addition to the instance properties of the Event interface, the event instance of CustomEvent also has the detail property.