Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

How to Easily Handle the onPaste Event in React

To handle the onPaste event on a React element, set its onPaste prop to an event handler. You can get the pasted text from the handler using event.clipboardData.getData('text').

For example:

JavaScript
import React, { useState } from 'react'; export default function App() { const [pasted, setPasted] = useState(''); const handlePaste = (event) => { setPasted(event.clipboardData.getData('text')); }; return ( <div> <input placeholder="Message" onPaste={handlePaste} type="text" id="message" /> <br /> You pasted: <b>{pasted}</b> </div> ); }
Handling the onPaste event on an element in React

The function (event listener) passed to the onPaste prop is called when the user pastes text into the input field.

The event object has various properties and methods used to get more info and take actions concerned with the event.

For the paste event, event has a clipboardData property that stores the data stored on the clipboard.

getData() gives us the data in the clipboard in a particular format. We pass 'text' as the first argument to get text data.

For the purposes of our example, we create a state that’ll be updated to the latest text data pasted in the input field. We display this text to the user.

Note: We used the useState hook to manage the state. This hook returns an array of two values, where the first is a variable that stores the state, and the second is a function that updates the state when it is called.

Handle onPaste event in entire window

To handle the paste event on the entire document window in React, set a paste event handler on the window object with addEventListener():

JavaScript
import React, { useState, useEffect } from 'react'; export default function App() { const [pasted, setPasted] = useState(''); useEffect(() => { const handlePaste = (event) => { setPasted(event.clipboardData.getData('text')); } window.addEventListener('paste', handlePaste) return () => { window.removeEventListener('paste', handlePaste) }; }) return ( <div> Pasted: <b>{pasted}</b> <br /> <input placeholder="Message" type="text" id="message" /> <br /> <input placeholder="Sender" type="text" id="sender" /> </div> ); }
Handling the onPaste event in the entire window in React

The addEventListener() method takes up to two arguments:

  1. type: a string representing the event type to listen for. 'paste' is for a paste event.
  2. listener: the function called when the event fires.

It also takes some optional arguments, which you can learn more about here.

We call addEventListener() in the useEffect hook to register the listener once the component renders as the page loads. We pass an empty dependencies array to useEffect so this registration happens only once. In the cleanup function, we call the removeEventListener() method to unregister the event listener and prevent a memory leak.

As we saw earlier, the event object has many methods and properties that let us get more info and take event-related actions.

For the paste event, event has a clipboardData property that contains the data stored on the clipboard.

The clipboard.getData() is the clipboard data in a specific format. Like before, we pass 'text' as the first argument to get text data.

Get clipboard data without paste

We may not want to wait for the user to do a paste before getting the clipboard data. In a case like this, the clipboard.readText() method from the navigator object helps:

JavaScript
import React, { useState } from 'react'; export default function App() { const [pasted, setPasted] = useState(''); const handlePaste = async (_event) => { const clipboardText = await navigator.clipboard.readText(); setPasted(clipboardText); } return ( <div> Pasted: <b>{pasted}</b><br /> <button onClick={handlePaste}>Paste</button> </div> ); }
Getting the clipboard data without pasting.

Here we wait for a click before getting the text in the clipboard.

readText() is an async method, so we await it in an async event handler to get the Promise‘s result.

Note

Before the browser can read clipboard data, it’ll show the user a dialog to grant permission first:

Browser shows popup to grant clipboard permissions.

Prevent onPaste event in React

Like for many other events, we can prevent the default UI action of the paste event with event.preventDefault() in the handler:

JavaScript
import React, { useState, useEffect } from 'react'; export default function App() { const [pasted, setPasted] = useState(''); useEffect(() => { const handlePaste = (event) => { // 👇 Prevent default paste UI action event.preventDefault(); setPasted(event.clipboardData.getData('text')); } window.addEventListener('paste', handlePaste) return () => { window.removeEventListener('paste', handlePaste) }; }) return ( <div> Pasted: <b>{pasted}</b> <br /> <input placeholder="Message" type="text" id="message" /> <br /> <input placeholder="Sender" type="text" id="sender" /> </div> ); }
Preventing the default paste action.

Key takeaways

To listen for pastes on an element and get clipboard text, we can use the event.clipboardData.getData() method. We can also handle pasted events on the entire window with window.addEventListener() and prevent the default UI action using event.preventDefault().

To get clipboard data without pasting, we use the clipboard.readText() method. These methods are useful for copying and pasting text between fields and preventing pasting behavior we don’t want.

How to Get the Current Page URL in React

We use the window.location.href property to get the current page URL in React.

For example:

JavaScript
import { useRef } from 'react'; export default function App() { const url = window.location.href; return ( <div> You are currently accessing <b>{url}</b> </div> ); }
Displaying the current URL in React.

We can use this same approach to get the current URL in Next.js

The window.location.href property returns a string that contains the entire page URL.

window.location contains other properties that give more information on the URL. Some of them are:

  • pathname: the path of the URL after the domain name and any optional port number.
  • protocol: the protocol scheme of the URL.
  • hostname: the hostname portion of the URL.

Here are some examples of using these properties to get various URL properties in addition to the full URL.

JavaScript
export default function App() { const url = window.location.href; const pathname = window.location.pathname; const protocol = window.location.protocol; const hostname = window.location.hostname; return ( <div> You are currently accessing <b>{url}</b><br /> Pathname: <b>{pathname}</b><br /> Protocol: <b>{protocol}</b><br /> Hostname: <b>{hostname}</b> </div> ); }
Displaying various URL properties.

Get current route in React Router

To get the current route in React Router, we use the useLocation() route.

For example:

JavaScript
import React from 'react'; import { Route, Link, Routes, useLocation } from 'react-router-dom'; function Home() { return <h2>Home</h2>; } function Products() { return <h2>About</h2>; } function Pricing() { return <h2>Pricing</h2>; } function Posts() { return <h2>Posts</h2>; } export default function App() { const location = useLocation(); const { hash, pathname, search } = location; return ( <div> <div> <Routes> <Route path="/products" element={<Products />} /> <Route path="/" element={<Home />} /> <Route path="/posts" element={<Posts />} /> <Route path="/#pricing" element={<Pricing />} /> </Routes> Pathname: <b>{pathname}</b><br /> Search params: <b>{search}</b><br /> Hash: <b>{hash}</b> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/products">Products</Link> </li> <li> <Link to="/posts?id=5">Posts</Link> </li> <li> <Link to="/#pricing">Pricing</Link> </li> </ul> </nav> </div> </div> ); }

useLocation() returns an object that contains information on the current page URL. Some of these properties are:

  • pathname: the part that comes after the domain name, e.g., /products.
  • search: the query string, e.g., ?id=5.
  • hash: the hash, e.g., #pricing.

Note

To get the full URL, we use location.href instead of useLocation().

JavaScript
const url = window.location.href;

Get dynamic route variable in React Router

To access the variables of a dynamic route directly in React Router, we use the useParams() hook.

For example:

JavaScript
import React from 'react'; import { Route, Routes, useParams } from 'react-router-dom'; function Posts() { const { id } = useParams(); return <h2>Settings for post {id} </h2>; } export default function App() { return ( <div> <div> <Routes> <Route path="/posts/:id" element={<Posts />} /> </Routes> </div> </div> ); }
Displaying the dynamic route variable.
Displaying the dynamic route variable.

The id variable corresponds to its placeholder value in the /posts/:id path. So as you saw in the example, the path /posts/5 will result in the id having a value of 5.

Get current route in Next.js app

To get the current route in a Next.js React app, we use the useRouter() hook:

The object useRouter() returns has a route property that is the current route in the Next.js app.

pages/posts.tsx
import Head from 'next/head'; import { useRouter } from 'next/router'; export default function Posts() { const posts = ['Post 1', 'Post 2', 'Post 3']; // 👇 Get route data const { route } = useRouter(); return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> Route: <b>{router}</b> <br /> {posts.map((post) => ( <p>{post}</p> ))} </main> </> ); }
Displaying the current route in Next.js

We use useRouter() to get data and take actions related to the current app route.

Get current dynamic route data in Next.js

To get data passed to a dynamic route, we use the query property from the useRouter() object:

For instance, we could have a route /posts/5 corresponding to a dynamic route, /posts/:id where 5 is the passed value for id.

Here’s how we’ll access it in the Next.js file that handles requests to the dynamic route:

pages/posts/[id].tsx
import Head from 'next/head'; import { useRouter } from 'next/router'; export default function Posts() { const { query } = useRouter(); // 👇 Get id value from dynamic route const { id } = query; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h2> Post <b>{id}</b> </h2> </main> </> ); }
Displaying the data passed with the dynamic route in Next.js

For the dynamic route to work, the file structure in the pages folder has to be like this: /pages/[id].tsx. We name the file according to what property we’ll use to access the data from the query, and we wrap the name in square brackets.

We use useRouter() to get data and take actions related to the current app route.

Get query parameter data in Next.js

We can also access URL query parameters (i.e., ?key1=value1) using the query object:

JavaScript
import Head from 'next/head'; import { useRouter } from 'next/router'; export default function Posts() { const { query } = useRouter(); // 👇 Get source from query params const { id, source } = query; return ( <> <Head> <title>Next.js - Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h2> Post <b>{id}</b> </h2> <h3>You came from {source}!</h3> </main> </> ); }
Display data passed with URL query parameters in Next.js

Key takeaways

In React, we can use window.location.href to get the current page URL, and useLocation() to get information on the current route in React Router. For dynamic routes, useParams() accesses the values of a dynamic route directly.

For Next.js, we use the useRouter() hook to get info on the current route. From the object, it returns, route has the current route, and query gives us info on data passed to the app with the URL, like dynamic route and query parameter data.

[SOLVED] ERR_REQUIRE_ESM: require() of ES Modules is not supported

Are you experiencing the “require() of ES modules is not supported” error (ERR_REQUIRE_ESM) in Node.js? This error happens when you try to import a package that is an ES-only module with the CommonJS require() syntax:

The "require() of ES modules is not supported (ERR_REQUIRE_ESM)" error happening.
The “require() of ES modules is not supported” error occurred.

To fix it, use the ES module import syntax for the module, or install a previous version of the package that supports require().

Use ES module import syntax

The ES module system is now the standard method for bundling JavaScript code for sharing and reusing. An ES module can only be used by other ES modules.

So to import ES modules into our project, we first have to define the project as an ES module too. We do this by setting the type field in our package.json file to "module".

JSON
{ "type": "module", // other fields... }

Once we do this, we can use the ES import syntax for the module, like this:

JavaScript
import chalk from 'chalk';

Note

If we don’t make our project an ES module, you’ll get another error:

The "Cannot use import statement outside a module" error occurred.

So this step is required.

Use async import() function

Another way you can fix the “require() of ES modules is not supported” error is to use the async import function that allows you to dynamically load modules:

For example, here’s how we can do it for chalk:

JavaScript
(async () => { const chalk = (await import('chalk')).default; console.log(chalk.blue('Coding Beauty')); })();

And this works:

Install previous version of package

It’s possible that the package used to support require() but no longer does. Maybe a popular package like chalk or node-fetch. In that case, you can also fix “require() of ES modules is not supported” error in Node.js by installing one of those versions that support require().

As the ES module format become more popular and we saw all the benefits, many popular libraries on NPM started to drop support for CommonJS. Unlike CommonJS, ES modules provide more flexible and powerful module system features like asynchronous loading and tree shaking (removing unused code at build time).

Here are the versions you should install for various well-known NPM packages to use CommonJS and require():

The version of popular packages to install that last supported CommonJS.

node-fetch

Install node-fetch version 2:

JavaScript
npm install node-fetch@2 # Yarn yarn add node-fetch@2

Note: Specify only the major version (use 2, not 2.x.x) so you can get all the latest important bug fixes published for version 2.

got

Install got version 11:

JavaScript
npm install got@11 # Yarn yarn add got@11

Note: Unlike node-fetch, got v11 is not being maintained anymore.

chalk

Install chalk version 4:

JavaScript
npm install chalk@4 # Yarn yarn add got@4

nanoid

Install nanoid version 3:

JavaScript
npm install nanoid@3 # Yarn yarn add nanoid@3

Others

If the package isn’t among the ones above, try browsing through its homepage or NPM package page to find any notices of dropped CommonJS support.

Conclusion

The “require() of ES modules is not supported” error occurs in Node.js when we attempt to use CommonJS require() on a package that is now an ES module. To fix it, we can use the ES module import syntax for the module, use the async import() function, or install a previous version of the package that supports require(). The ES module system is better as it provides powerful features like asynchronous loading and tree shaking, making it the preferred method for bundling JavaScript code.

How to Get the Sum of an Array in JavaScript

To get the sum of an array in JavaScript, call the reduce() method on the array, with two arguments: a callback that takes two arguments and returns their sum, and 0.

For example:

JavaScript
const sum = (arr) => arr.reduce((a, b) => a + b, 0); const arr = [1, 2, 3, 4, 5] const result = sum(arr); console.log(arr); // 15

When we call reduce() method on arr, it loops through the array and adds each element to a sum value When the loop is done, this value will hold the total sum of the array, and reduce() will return it.

The callback argument is called on each array element and takes two arguments, a and b. a represents the total sum value so far and b represents the current element in the iteration. The callback simply adds the current element to the total sum value so far and returns it.

The second argument reduce() takes is an initial value of the total sum. We set it to 0 in this case, but this is the default value anyway, so we can leave it out:

JavaScript
// No need for second argument when it's zero const sum = (arr) => arr.reduce((a, b) => a + b); const arr = [1, 2, 3, 4, 5] const result = sum(arr); console.log(arr); // 15

Get sum of array with for..of loop

Alternatively, we can get the sum of an array in JavaScript using a for..of loop and taking these steps:

  1. Create a variable to store the sum.
  2. Loop over the array.
  3. Add each element to the sum.

For example:

JavaScript
function sum(arr) { let result = 0; for (const item of arr) { result += item; } return result; } const arr = [1, 2, 3, 4, 5] const result = sum(arr); console.log(arr); // 15

Throughout the loop, item will hold the value of each array element, so we add its value to sum in each iteration.

Get sum of numbers with forEach() method

Of course, wherever we can use for..of we can use forEach():

JavaScript
function sum(arr) { let result = 0; arr.forEach(item => { result += item; }); return result; } const arr = [1, 2, 3, 4, 5] const result = sum(arr); console.log(result); // 15

The forEach() loops over each element in the arr array. It takes a callback function as its argument that is called on each element of the array. Like we did with for..of, the callback function simply adds the current element to the result variable.

Get sum of numbers with for loop

And forEach() or for...of can equally be replaced with the traditional for loop:

JavaScript
function sum(arr) { let result = 0; for (let i = 0; i < arr.length; i++) { result += arr[i]; } return result; } const arr = [1, 2, 3, 4, 5] const result = sum(arr); console.log(result); // 15

How do they compare in speed?

We performed a test to compare the running times of the four different methods above for summing an array in JavaScript: the for loop, forEach(), for...of loop, and reduce() methods.

We tested each method three times and noted how long it took to complete each test. Then we averaged the results to get a more accurate representation of the execution times.

Each test case involved summing an array of the first 1 million positive integers.

Speed comparison of the different methods of getting the sum an array in JavaScript.
Speed comparison of the different methods.

The for loop method was the fastest, taking only an average of 4.530 ms to complete. The forEach() method was the slowest, with an average execution time of 31.123 ms. The for...of loop and reduce() methods were relatively close in execution time, with average execution times of 22.940 ms and 21.463 ms, respectively.

Overall, the for loop method was the most efficient for summing an array in JavaScript, while the forEach() method was the least efficient. Still, the best method to use depends on your specific use case and the array’s size.

When dealing with small arrays, the difference in performance between different methods for summing the array may not be noticeable. But as the size of the array increases, this difference can become more significant and can affect the code’s overall running time.

So for very large arrays, it’s important that we choose the most efficient method for computing the sum to avoid slow execution times. By choosing the most efficient method, we’ll make sure that our code runs as quickly and efficiently as possible, even when dealing with huge amounts of data.

How to Fix the “structuredClone is not defined” Error in Node.js

The “structuredClone is not defined” error occurs when you try to use the structuredClone()/ method in JavaScript, but it’s not defined.

The "structuredClone is not defined" error occuring in a terminal.
The “structuredClone is not defined” error occuring in a terminal.

To fix it, install Node.js 17 or a newer version. Once you’ve updated Node.js, you can use structuredClone() to clone objects with all their properties and methods.

What causes the “structuredClone is not defined” error?

If you try to use the structuredClone() method in a script that’s running with a Node.js version lower than 17, you will encounter this error.

The structuredClone() method is used to create a deep copy of an object. It’s a built-in function in JavaScript and is used to clone an object with all its properties and methods.

But when the structuredClone() method is not defined, it means that the server environment doesn’t recognize the function and cannot perform the action.

Fix: update Node.js

To fix the “structuredClone is not defined” error in JavaScript, you need to install Node.js 17 or a newer version. If you’re using an older version of Node.js, it will throw an error when you try to use structuredClone().

Install from website

To download Node.js, visit the official website and opt for the LTS version, as it offers superior stability. As of the time of writing this article, the most recent LTS release of Node.js is v18.15.0.

The Node.js download page on the official website.
The Node.js download page on the official website.

Install with Chocolatey

If you’re using Chocolatey, Node.js is available as the nodejs package, meaning you can easily install it in a terminal using the following command.

Shell
# Use current LTS version choco install nodejs --version=18.5.0

After installing, you can use the structuredClone method to clone an object:

JavaScript
const obj = { name: 'Mike', friends: [{ name: 'Sam' }] }; const clonedObj = structuredClone(obj); console.log(obj.name === clonedObj); // false console.log(obj.friends === clonedObj.friends); // false

Key takeaways

If you get the “structuredClone is not defined” error when using the structuredClone() method in JavaScript, it means that the method is unavailable. To fix the problem, update your Node.js to a version newer than 17. You can get the latest version from the official Node.js website or install the nodejs package using Chocholatey.

How to Simulate a KeyPress in JavaScript

To simulate a keypress in JavaScript:

  1. Get the text field element with a method like document.querySelector().
  2. Create a new KeyboardEvent object.
  3. Call the dispatchEvent() method on the text field, with the KeyboardEvent object.

i.e.:

JavaScript
function simulateKeyPress(key) { const event = new KeyboardEvent('keydown', { key }); textField.dispatchEvent(event); }

“Text field” here might be an input element, textarea element, or even a content editable div.

A KeyboardEvent object describes a user’s interaction with the keyboard. Its constructor takes two arguments:

  • type – a string with the name of the event. We pass 'keydown' to indicate that it’s the event of a key press.
  • options – an object used to set various properties of the event. We used the object’s key to set the keyboard key name associated with our key press.

For example:

HTML
<input type="text" name="text-field" id="text-field" placeholder="Text field" /> <br /> Key presses: <span id="key-presses">0</span> <br /><br /> <button id="simulate">Simulate</button>
JavaScript
const textField = document.querySelector('#text-field'); const keyPresses = document.getElementById('key-presses'); const keyPressed = document.getElementById('key-pressed'); const simulate = document.getElementById('simulate'); // Set 'keydown' event listener, for testing purposes let keyPressCount = 0; textField.addEventListener('keydown', (event) => { keyPressCount++; keyPresses.textContent = keyPressCount; keyPressed.textContent = event.key; }); simulate.addEventListener('click', () => { simulateKeyPress('a'); }); function simulateKeyPress(key) { const event = new KeyboardEvent('keydown', { key }); textField.dispatchEvent(event); }

First, we use selector methods like document.querySelector() and document.getElementById() to get an object representing the various elements to be used in the JavaScript code.

Then, we call the addEventListener() method on the text field object to set an event listener for the keydown event. When the user types a key or input is simulated from a script, the event listener will be fired, incrementing the key press count and displaying the most recently pressed key.

We also call the addEventListener() method on the simulate button object for the click event to simulate the key press when the user clicks the button.

Simulating a keypress fires the key event.
Simulating a keypress fires the key event.

Notice that the key is not entered in the text field. This is because of the isTrusted property, which indicates whether a user action or script generated an event. When isTrusted is false, the event is not considered trusted and does not reflect visually in the text field. Browsers do this for security reasons.

JavaScript
const event = new KeyboardEvent('keydown', { key, ctrlKey: true }); console.log(event.isTrusted); // false

isTrusted is a readonly property and will only be true when an actual user’s action caused the event; in this case: typing on the keyboard.

Insert value into input field or textarea

If you want to enter a key into the text field programmatically, you’ll have to use other approaches. For input and textarea elements, here’s a method you can use:

JavaScript
function insertTextAtCursor(element, text) { element.focus(); const startPos = element.selectionStart; const endPos = element.selectionEnd; element.value = element.value.substring(0, startPos) + text + element.value.substring(endPos, element.value.length); element.selectionStart = element.selectionEnd = startPos + text.length; }

This function takes the text field element and some text as arguments and inserts the text into the text field, replacing any highlighted text before the insertion.

You can also use the insert-text-at-cursor NPM package to insert text into an input field or textarea. Its default export function works like the one above.

JavaScript
import insertTextAtCursor from 'insert-text-at-cursor';

Either function can be called like this:

JavaScript
insertTextAtCursor(textField, 'Coding Beauty');

Simulate keypress in input field with key modifier

Sometimes, you might want to simulate a key combination that includes the modifier keys, e.g., Ctrl + A, Ctrl + Shift + C, etc. There are option properties you can set to do this.

For instance, setting the ctrlKey property to true simulates the Ctrl + {key} combination, where {key} is the value assigned to the key property.

JavaScript
// Ctrl + c, Ctrl + o, Ctrl + d, Ctrl + e const keysToSend = 'code'; let keyIndex = 0; simulate.addEventListener('click', () => { simulateKeyPress(keysToSend.at(keyIndex++) || keysToSend.at(-1)); }); function simulateKeyPress(key) { const event = new KeyboardEvent('keydown', { key, ctrlKey: true }); textField.dispatchEvent(event); }
Simulating various keys with the Ctrl modifier.
Simulating various key combinations with the Ctrl modifier.

Some other important key modifier option properties are:

  • altKey: adds the Alt key to the key combination, e.g., Alt + Z, Ctrl + Alt + N, etc.
  • ctrlKey: adds the Ctrl key to the key combination, e.g., Ctrl + A, Ctrl + Shift + T, etc.
  • shiftKey: adds the Shift key to the key combination.
  • metaKey: adds the ⌘ key on MacOS and the Windows key on Windows to the key combination.

Key takeaways

We can easily simulate keypresses in JavaScript on a text field by calling the dispatchEvent() method on the element object, passing a custom-created KeyboardEvent object as an argument. While this will trigger the appropriate key events set on the element, it would not visually reflect on the text field since programmatically created events are not trusted for security reasons.

How to Set Focus on the Next Form Input With JavaScript

To move focus from one input to the next one in a form:

  1. Get a list of all the input elements in the form.
  2. Get the index of the input element in the list that has focus.
  3. Get the index of the next input element in the list.
  4. Focus on it.
JavaScript
function focusNext() { const currInput = document.activeElement; const currInputIndex = inputs.indexOf(currInput); const nextinputIndex = (currInputIndex + 1) % inputs.length; const input = inputs[nextinputIndex]; input.focus(); }

For example:

HTML
<form class="form"> <input type="number" name="num1" id="num1" placeholder="1st Number" maxlength="2" /> <input type="number" name="num2" id="num2" placeholder="2nd Number" maxlength="3" /> <input type="number" name="num3" placeholder="3rd Number" id="num3" maxlength="4" /> <button type="submit" id="submit-btn">Submit</button> </form>
CSS
.form { display: flex; flex-direction: column; width: 200px; } .form input:not(:first-of-type) { margin-top: 10px; } .form #submit-btn { margin-top: 20px; }
JavaScript
// Convert NodeList to Array with slice() const inputs = Array.prototype.slice.call( document.querySelectorAll('.form input') ); inputs.forEach((input) => { input.addEventListener('keydown', (event) => { const num = Number(event.key); if (num && num >= 0 && num <= 9) { // Only allow numbers if (input.value.length >= input.maxLength) { event.preventDefault(); focusNext(); } } }); }); function focusNext() { const currInput = document.activeElement; const currInputIndex = inputs.indexOf(currInput); const nextinputIndex = (currInputIndex + 1) % inputs.length; const input = inputs[nextinputIndex]; input.focus(); }
The next input gains focus when the input limit is reached.
The next input gains focus when the input limit is reached.

We use the document.querySelectorAll() method to obtain a collection of all the input elements in the form. This method in JavaScript allows you to find all the elements on a web page that match a certain pattern or characteristic, such as all elements with a particular class name or tag name.

We use the forEach() method to iterate over the array of input elements we obtained using document.querySelectorAll(). For each input element, we add an event listener to listen for the keydown event.

When a key is pressed down, we check if the key pressed is a number between 0 and 9. If it is, we check if the length of the input’s value is equal to its maxLength attribute. If it is, we prevent the default action of the event and call the focusNext() function to move the focus to the next input element.

The forEach() method is a higher-order function in JavaScript that allows you to run a function on each element of an array.

Tip: A higher-order function is a function that can take in functions as arguments and/or return a function.

In the focusNext() function, we first get the currently focused input element using document.activeElement. We then get the index of this input element in the inputs array we created earlier using inputs.indexOf(currInput).

We then calculate the index of the next input element in the array using (currInputIndex + 1) % inputs.length, where % is the modulo operator. This ensures that if the currently focused input element is the last one in the array, we wrap around to the first input element.

Finally, we get a reference to the next input element using inputs[nextinputIndex] and call the focus() method on it to move the focus to the next input element.

Set focus on next input on enter

Sometimes, we want to move the focus to the next input element when the user presses the Enter key instead of waiting for the input’s maxLength to be reached. To do this, we can add an event listener to listen for the keydown event on each input element. When the Enter key is pressed, we prevent the default action of the event and call the focusNext() function to move the focus to the next input element.

JavaScript
inputs.forEach((input) => { input.addEventListener('keydown', (event) => { if (event.key === 'Enter') { event.preventDefault(); focusNext(); } }); });

Now, when the user presses the Enter key, the focus will move to the next input element. This can be especially useful in forms where the user needs to quickly move through a series of inputs without having to manually click on each one.

Get Started with MutationObserver: Everything You Need to Know

The MutationObserver API allows tracking changes to the DOM tree, including when elements are added, removed, modified, or have an attribute changed. It can also track changes to an element’s contents or styles, such as the addition or deletion of text or when a style property is modified.

We’ll look at how to use the Mutation API in this article and real-world use cases to see its importance.

Mutation Observer in action

Let’s look at the Mutation Observer API in action right away:

JavaScript
// Usage const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { const el = mutation.target; if (el.textContent === 'Hello!') { el.textContent = 'Welcome!'; } } }); const textEl = document.getElementById('info'); observer.observe(textEl, { childList: true }); // Test const changeText = document.getElementById('change-text'); changeText.addEventListener('click', () => { textEl.textContent = 'Hello!'; });
The displayed text is changed by Mutation Observer.
The displayed text is changed by Mutation Observer.

Create a Mutation Observer

We create a Mutation Observer using the MutationObserver() constructor. The constructor accepts a callback that will be called when a mutation is detected on an element.

The callback is passed an array of MutationRecord objects, each containing information about the particular mutation that just occurred.

JavaScript
const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { // Process mutations... } });

Two essential properties that a MutationRecord object has are the target and type property.

The target property holds the element that was mutated and type contains the type of mutation that just occurred. We can use these two properties to identify what kind of mutation happened and take the appropriate action.

For instance, we can check if the mutation was an attribute change, a child node change, or a text node change and then act accordingly. type can take the following values:

  • attributes: attribute change
  • characterData: text node change
  • childList: child node change

We can then use this data to take the appropriate action in our callback. For example, if a change to an element’s child nodes is detected, we can update the UI to reflect the new changes.

JavaScript
const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { const type = mutation.type; const element = mutation.target; console.log(`${mutation.type} mutation on element #${element.id}`); } });

Observe changes with Mutation Observer

Once we have created a Mutation Observer, we can use the observe() method to start observing changes in an element. The observe() method takes two arguments: the element to observe and the configuration object. The configuration object can contain options to configure what kind of mutations to watch for. These options include childList, attributes, and characterData.

For example, if we want to watch for changes in an element’s child nodes, we can set the childList option to true. Similarly, if we’re going to watch for changes to attributes and text nodes, we can set the attributes and characterData option to true respectively.

Once we have configured our Mutation Observer and started observing changes, we can react to any changes.

Stop watching for changes in element

Once we have started observing changes, we can stop watching for changes at any time by calling the disconnect() method on the Mutation Observer. This will immediately stop watching for changes in the element, and the observe() method will no longer be called. This can be useful when you no longer need to watch for changes in an element and want to free up memory and resources.

JavaScript
observer.disconnect();

Use MutationObserver in the real-world

In many cases, you may encounter an external script that brings a range of valuable features and capabilities but brings about unwanted visual effects, like displaying text with content you’d like to customize but can’t. In this type of scenario, Mutation Observer can be used as a workaround. This tool can detect when the text content is changed in the DOM and automatically replace it with something more suitable for the task.

Get all pending mutations with takeRecords()

Mutation Observer is a powerful JavaScript API that detects changes to DOM tree elements, such as added/removed components, changed attributes, altered text content, and changed styles. A practical use is to detect and customize content set by external scripts. Create a Mutation Observer with a callback function and use observe() it to start monitoring and disconnect() to end it. takeRecords() retrieves all pending Mutation Records.

How to Get the Current Mouse Position in JavaScript

To get the current position of the mouse in JavaScript, add a mousemove event listener to the window object and access the clientX and clientY properties of the MouseEvent object in the listener to get the X and Y coordinates of the mouse respectively.

For example:

HTML
<p> Mouse pos: <b><span id="mouse-pos"></span></b> </p>
JavaScript
const mousePosText = document.getElementById('mouse-pos'); let mousePos = { x: undefined, y: undefined }; window.addEventListener('mousemove', (event) => { mousePos = { x: event.clientX, y: event.clientY }; mousePosText.textContent = `(${mousePos.x}, ${mousePos.y})`; });
The current mouse position is shown.
The current mouse position is shown.

The mousemove event is triggered on an element when the mouse hovers it. To be more precise, it is fired when the mouse is moved and the cursor’s hotspot is within the element’s bounds.

We attach the event listener to the window object to trigger the event whenever the mouse has moved anywhere on the page.

The mousemove event listener receives a MouseEvent object used to access information and perform actions related to the event. We use the clientX and clientY properties of this object to get the position of the mouse on the X-coordinate and Y-coordinate respectively in the application’s viewport.

Get current mouse position relative to element in React

In the first example, we get the current mouse position in global coordinates. In global coordinates, position (0, 0) is at the top-left of the webpage and position (Xmax, Ymin) is at the bottom right.

We might instead want to get the mouse position within the region of an element.

To get the current mouse position relative to an element, set a mousemove event handler on the element, then calculate the local X and Y positions using properties of the MouseEvent object passed to the event handler.

For example:

HTML
<div> <div class="local"> Local <br /> <b><span id="local-mouse-pos"></span></b> </div> <p> Global <br /> <b><span id="global-mouse-pos"></span></b> </p> </div>
CSS
.local { border: 1px solid #c0c0c0; padding: 75px; text-align: center; display: inline-block; margin-left: 100px; margin-top: 100px; }
JavaScript
const globalMousePosText = document.getElementById('global-mouse-pos'); const localMousePosText = document.getElementById('local-mouse-pos'); let localMousePos = { x: undefined, y: undefined }; let globalMousePos = { x: undefined, y: undefined }; window.addEventListener('mousemove', (event) => { const localX = event.clientX - event.target.offsetLeft; const localY = event.clientY - event.target.offsetTop; localMousePos = { x: localX, y: localY }; globalMousePos = { x: event.clientX, y: event.clientY }; globalMousePosText.textContent = `(${globalMousePos.x}, ${globalMousePos.y})`; localMousePosText.textContent = `(${localMousePos.x}, ${localMousePos.y})`; });

Now the resulting X and Y coordinates will be relative to the element. For example, position (0, 0) will be at the top left of the element, not the viewport:

The current mouse position relative to the element in shown.
The current mouse position relative to the element is shown.

We subtract the offsetLeft property of the element from the clientX property of the MouseEvent object to get the position on the X-axis relative to the element.

Similarly, to get the position on the Y-axis, we subtract the offsetTop property from the clientY property of the MouseEvent object.

JavaScript
window.addEventListener('mousemove', (event) => { const localX = event.clientX - event.target.offsetLeft; const localY = event.clientY - event.target.offsetTop; localMousePos = { x: localX, y: localY }; // ... });

The offsetLeft property returns the number of pixels between the left position of an element and its parent.

Likewise, the offsetTop property returns the number of pixels between the top position of an element and its parent.

How to Check if String Contains Whitespace in JavaScript

To check if a string contains whitespace in JavaScript, call the test() method on this regex: \s, i.e., /\s/.test(str). test() will return true if the string contains any whitespace character. Otherwise, it will return false.

JavaScript
function containsWhitespace(str) { return /\s/.test(str); } console.log(containsWhitespace(' ')); // true console.log(containsWhitespace('JavaScript')); // false console.log(containsWhitespace('coding beauty')); // true console.log(containsWhitespace('string\twith\ttabs')); // true console.log(containsWhitespace('string\nwith\nnewline')); // true

The RegExp test() method searches a string for matches with a regular expression. It returns true if any matches are found. Otherwise, it returns false.

The forward slashes / and / indicate the start and end of the regular expression.

The \s matches any single whitespace character in the string.

This method will match any whitespace character, including:

  • space (' ')
  • tab (\t)
  • carriage return (\r)
  • line feed (\n), and
  • vertical tab (\v)
JavaScript
// space (' ') console.log(containsWhitespace('coding beauty')); // true // carriage return (\r) console.log(containsWhitespace('coding\rbeauty\r')); // true // line feed (\n) console.log(containsWhitespace('coding\nbeauty\n')); // true // form feed (\f) console.log(containsWhitespace('coding\f\beauty\f')); // true // vertical tab (\v) console.log(containsWhitespace('coding\vbeauty\v')); // true

If you only to check if the string contains a space character, you’ll need to use a different approach…

Check if string contains only spaces

To check if a string contains only spaces, simply change the regex to a space character:

JavaScript
function containsWhitespace(str) { return / /.test(str); } console.log(containsWhitespace('coding beauty')); // true console.log(containsWhitespace('coding\rbeauty\r')); // false console.log(containsWhitespace('coding\nbeauty\n')); // false console.log(containsWhitespace('coding\f\beauty\f')); // false console.log(containsWhitespace('coding\vbeauty\v')); // false

You can also use call the String includes() methods with a space character to check if such a character exists in the string.

JavaScript
function containsWhitespace(str) { return str.includes(' '); } console.log(containsWhitespace('coding beauty')); // true console.log(containsWhitespace('coding\rbeauty\r')); // false console.log(containsWhitespace('coding\nbeauty\n')); // false console.log(containsWhitespace('coding\f\beauty\f')); // false console.log(containsWhitespace('coding\vbeauty\v')); // false

Check if string contains whitespace with String match()

We can use the call the match() method on a string with the /\s/ as an argument to check whether the string contains whitespace.

JavaScript
function containsWhitespace(str) { return Boolean(str.match(/\s/)); } console.log(containsWhitespace(' ')); // true console.log(containsWhitespace('JavaScript')); // false console.log(containsWhitespace('coding beauty')); // true console.log(containsWhitespace('string\twith\ttabs')); // true console.log(containsWhitespace('string\nwith\nnewline')); // true

Like the RegExp test() method, match() searches a string for matches with a regular expression, but it returns an array of the matches, instead of a boolean value.

JavaScript
// [ ' ', index: 6, input: 'coding beauty', groups: undefined ] console.log('coding beauty'.match(/\s/));

In this case, match() returns an array that contains the first match of a whitespace character, along with some additional properties that provide more information on the match.

If there are no matches found in the string, match() returns null:

JavaScript
console.log('Coding_Beauty'.match(/\s/)); // null

Because of how match() works, we can cast the return value to a boolean, whose value would indicate whether or not any matches of a whitespace character exist in the string.

The Boolean() constructor casts a truthy or false value to true or false. An array of matches from match() will be cast to true, indicating the presence of matches, and a null value from match() will be cast to false, meaning that no matches can be found.

Note: In JavaScript, there are six falsy values: undefined, null, NaN, 0, '' (empty string), and false. Every other value is truthy.