Locate the preceding element of the same type without considering its parent

Is there a way to locate the preceding element of a specific type, whether it belongs to the same parent or not?

For instance, I am interested in identifying the prior input[type="text"] element and giving it focus.

Currently, I can target the previous sibling within the same parent, but I would like to refine that to exclusively select input[type="text"] elements and extend it to encompass the previous parent as well.

The answer that follows should utilize vanilla JavaScript exclusively.

document.addEventListener('keydown', function(e) {
  // if backspace is pressed and the input is empty
  if (e.keyCode === 8 && e.target.value.length === 0) {
    // This will set focus to the previous input element
    e.target.previousSibling.previousSibling.focus();
  }
}, false);
<div>
  <input type="text">
  <input type="text">
</div>
<div>
  <input type="text>
  <input type="text">
</div>
<div>
  <input type="text">
  <input type="text">
</div>

Answer №1

To efficiently navigate to the previous input element when using `querySelectorAll`, you can loop through all matching elements and focus on the one preceding the current target. Remember that the result of `querySelectorAll` is in "document order".

document.addEventListener('keydown', function(e) {
  if (e.keyCode === 8 && e.target.value.length === 0) {
    // This should give focus to the previous input element
    var inputs = document.querySelectorAll('input[type="text"]');

    for(let i = 1; i < inputs.length; i++){
        if(inputs[i] == e.target){
            inputs[i-1].focus();
            break;
        }
    }
  }
}, false);
<div>
  <input type="text">
  <input type="text">
</div>
<div>
  <input type="text">
  <input type="text">
</div>
<div>
  <input type="text>
  <input type="text>
</div>

Answer №2

There is a more efficient way to handle events on specific elements within a document rather than listening to all events occurring on the entire document.

Start by selecting and caching the main element that contains the elements you wish to cycle through.

Then, select and cache all the elements you want to cycle through from the previously selected scope and store them in a list.

Next, iterate through each element in the list using a loop and perform the following steps:

  1. Create an Immediately Invoked Function Expression (IIFE) to establish a new lexical scope for storing the index associated with the current element.
  2. Add an event listener for the 'keydown' event to the element, checking for the backspace key press when the field is empty; if the conditions are met, either focus on the previous element in the list or focus on the last element if the current one is the first.

By utilizing this approach:

  • You minimize DOM queries (within a specified scope),
  • You do not need to listen to every keydown event across the entire document,
  • And you can create an infinite cycling effect from start to finish.

var scope = document.querySelector('.scope');
var inputs = scope.querySelectorAll('input[type="text"]');
for (var i in Object.keys(inputs)) (function(index){
    inputs[i].addEventListener('keydown', function(e){
        if (e.which === 8 && this.value.length === 0) {
            var next = index - 1;
            if (next < 0) next = inputs.length - 1;
            inputs[next].focus();
        }
    }, false);
})(i);
<div class="scope">
    <div><input type="text"><input type="text"></div>
    <div><input type="text"><input type="text"></div>
    <div><input type="text"><input type="text"></div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking for assistance with implementing touch gestures on an HTML website?

I am in the process of developing a web application, and I have implemented a menu bar that shifts when a user clicks on an arrow. Each click activates a new menu option. Currently, I am looking to provide users with the ability to swipe over the screen t ...

Storing files or Blobs within Json data in Angular/Javascript

Is it possible to include a file inside a JSON when sending data through ajax? colors: [ {_id: "5bec42f02797800f447241d1", color: "#777", image: File(79666)}, {_id: "5bec8cf91fb21b3a2477d817", color: "#566", image: File(79666)} ] If not, what is the alt ...

Generate a compressed file from a readable source, insert a new document, and transfer the output

The objective is to obtain an archive from the client, include a file, and transfer it to Cloud Storage without generating a temporary file. Both the client and server utilize the archiver library. The issue with the code snippet provided is that the file ...

Troubleshooting table alignment problem in Internet Explorer 9

Check out I'm facing an issue with the alignment of the four small images on the right side. It looks fine in Firefox and Chrome, but in IE9 they are spreading out... Here is a snippet of the CSS: .fixedtable{ width: 90px; overflow: hidden; text- ...

Nested Flexbox Elements

Looking to nest elements using flexbox in order to achieve the following layout: https://i.sstatic.net/bEKps.png Does anyone know how to make this happen? ...

How can I stack two appbar components from Material Ui on top of each other without the vertical line separating them?

I am facing a challenge while trying to incorporate two AppBar components in Material-UI, stacked one on top of the other. The problem arises when a line appears at the end of the first AppBar, overlapping with the second one. Click here to view an image ...

Ways to modify the color of a selected dropdown in a navigation bar

Every time I click on the dropdown menu, it gets highlighted in blue. Is there a way to change this using Bootstrap or by adjusting my CSS? I've already attempted changing the color with this CSS element: .dropdown-item.active, .dropdown-item:active ...

HTML - various incorrect horizontal alignments

I'm having trouble getting the site logo, site name, and site header to align horizontally on my website. They keep ending up in different places.https://i.stack.imgur.com/5yL5f.jpg I'd like it to look similar to this: https://i.stack.imgur.com/ ...

What is the best way to manage a vuex dispatch response?

Despite feeling like the answer is right in front of me, I'm waving the white flag and seeking suggestions. The challenge lies in my login form that submits to an AWS API and reacts to the result. The trouble starts when the handleSubmit method is tr ...

Tips on efficiently rebinding jQuery events to dynamically loaded content without having to manually do it for each event or class

Recently, I encountered an issue with my jQuery app where I needed to bind different functions to elements within one div dynamically. Specifically, I had a "delete-function" attached to all ".btn-delete" elements and an "add-function" linked to all ".btn- ...

Ways to display the main image on a blog post

This piece of code is designed for displaying the relevant post associated with wp_ai1ec_events function display_event($atts ) { global $wpdb; $event = $wpdb->get_results("SELECT * FROM wp_ai1ec_events ORDER BY start"); ...

Issues with toggling the menu on Angular 14 using Bootstrap 4.6

I am struggling with implementing a menu on the header section of my Angular 14 homepage. The menu I added is not opening as expected. Even after trying various working menu samples from the internet, I couldn't get it to work in my project. Here are ...

When a text is lengthy, the ellipsis (three dots) will not be displayed

I have applied the following style: div>span { display: flex; flex: 1 0 0; align-self: center; align-items: center; justify-content: flex-end; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } Interestingly, the stylin ...

What is the method for adding up elements based on their identification numbers?

Is it possible to calculate the sum of multiple range sliders using their unique IDs? Multiplying each range slider value by the corresponding input. And finally, adding up all the multiplication results. $(document).ready(function() { $(".range") ...

Firefox having trouble loading ThreeJS

My current project involves showcasing 3D files online using ThreeJS. While it operates smoothly on Chrome and MS Edge, I encountered a hitch on Firefox: Uncaught TypeError: Error resolving module specifier “three”. Relative module specifiers must star ...

Tips for extracting subdomains from URLs

Looking for a way to extract only the 'http://abc' part from a URL like http://abc.xyz.com, unfortunately getting the full 'http://abc.xyz.com'. I attempted using: windw.location.origin Do I need to implement an additional method to a ...

Matching an element that contains a specific string in JS/CSS

I'm currently faced with an HTML file that's being generated by an outdated system, making it tricky for me to control the code generation process. The structure of the HTML code is as follows: <table cellpadding=10> <tr> ...

What is the correct way to place an item within a grid layout?

My current layout is structured with a single row class and two columns using the bootstrap grid system. However, I am facing an issue where I need to add another item within that grid system, but I am struggling to position it correctly. It keeps appeari ...

What is the best way to update comments after submitting an AJAX request?

I stumbled upon a lightweight script that allows for submitting WordPress comments via AJAX. Although the comments are successfully submitted, the new comment does not appear immediately; only the comment count gets updated. Upon manually refreshing the pa ...

Is it possible to eliminate jitter in Socket.io?

I've searched everywhere online for a solution to this problem but haven't found one yet. I need help eliminating potential jitter on my Node.js server while using socket.io for connections. Whenever a user visits a specific section of my websit ...