When using JS, the open and close buttons function properly, however, the escape key always attempts to close the most recent modal

My buttons are working fine, but I'm having trouble getting the escape key to work with the correct modal. It keeps closing the last modal no matter how many I have.

Even though thisModal seems to point to the right one for the buttons, it doesn't work properly with the document.onkeydown function, and I can't figure out why since everything is within the same for loop.

And please, let's keep any comments about using jQuery to a minimum :).


          const modalToggle = document.querySelectorAll(".button"),
            modal = document.querySelectorAll(".modal"),
            closeButton = document.querySelectorAll(".close");

          if (modalToggle) {

            for (i = 0; i < modalToggle.length; i++) {
              let thisToggle = modalToggle[i];
              let thisModal = modal[i];
              let thisClose = closeButton[i];

              thisToggle.addEventListener("click", () => openModal(thisModal));
              thisClose.addEventListener("click", () => closeModal(thisModal));
              document.onkeydown = (e) => {
                if (e.keyCode == 27) {
                  console.log(thisModal); // Always displays the LAST modal... why?
                  closeModal(thisModal);
                }
              }
            };
          }

          function openModal(el) {
            el.style.display = "block";
          }

          function closeModal(el) {
            el.style.display = "none";
          }
        
      

          .modal {
            display: none;
            background: lightgray;
            border: 1px solid black;
            width: 50%;
            height: 100px;
          }
        
      

          <button class="button">One</button>
          <button class="button">Two</button>
          <button class="button">Three</button>

          <div class="modal">ONE
            <button class="close">Close</button>
          </div>

          <div class="modal">TWO
            <button class="close">Close</button>
          </div>

          <div class="modal">Three
            <button class="close">Close</button>
          </div>
        
      

Answer №1

One issue was that each iteration of the for loop was replacing the previous bind. To resolve this, try modifying the code so that pressing the escape key closes all modals.

const modalToggle = document.querySelectorAll(".button"),
  modal = document.querySelectorAll(".modal"),
  closeButton = document.querySelectorAll(".close");

if (modalToggle) {

  for (i = 0; i < modalToggle.length; i++) {
    let thisToggle = modalToggle[i];
    let thisModal = modal[i];
    let thisClose = closeButton[i];

    thisToggle.addEventListener("click", () => openModal(thisModal));
    thisClose.addEventListener("click", () => closeModal(thisModal));
  };
  document.onkeydown = (e) => {
      if (e.keyCode == 27) {
          for (i = 0; i < modalToggle.length; i++) {
               let thisToggle = modalToggle[i];
              let thisModal = modal[i];
              let thisClose = closeButton[i];
              console.log(thisModal); // Why is this always the last modal?
              closeModal(thisModal);
          };


      }
    }
}

function openModal(el) {
  el.style.display = "block";
}

function closeModal(el) {
  el.style.display = "none";
}
.modal {
  display: none;
  background: lightgray;
  border: 1px solid black;
  width: 50%;
  height: 100px;
}
<button class="button">One</button>
<button class="button">Two</button>
<button class="button">Three</button>

<div class="modal">ONE
  <button class="close">Close</button>
</div>

<div class="modal">TWO
  <button class="close">Close</button>
</div>

<div class="modal">Three
  <button class="close">Close</button>
</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

When I try to run "npm start" with node-webkit, it seems like the script specified in my package.json manifest file is not being

After running npm start in the terminal, I encountered the following error message: PS C:\Users\finsa\OneDrive\Documents\UNI\Web Development\NS_Music_App> npm start > <a href="/cdn-cgi/l/email-protection" class= ...

Updating Multiple Divs with jQuery AJAX (Continuous Repeated Refreshing)

I've been trying for a while to solve this issue but haven't found a solution yet. My auto-refresh feature works, however, it refreshes all the divs inside each other. For example, I have a computer-aided dispatch application with sections for av ...

Trouble is arising in rendering events with years before 100 (specifically years 0000 - 0099) when using the ISO8601 format in fullCalendar

I've created a Calendar that showcases various events using fullcalendar. The events span from the years 0001 to 6000. Fullcalendar requires dates in ISO8601 format, and I am providing them as such. Events from the years 0100-6000 render perfectly w ...

I have a specific resolution in mind where I want to run jQuery code during window scrolling

I have a jQuery code that I want to run only when the resolution is greater than 950px. If not, I risk losing the responsive logo. My goal is to create a navigation bar similar to the one on the Lenovo homepage. $(document).ready(function(){ //left ...

The Meteor update is unsuccessful on the Mongo Sub Collection and will not continue

I am currently facing an issue with updating a specific object within an array in my object based on a value. Whenever I try to add the update code, the function gets stuck at that point without proceeding further. None of the console.log calls after the u ...

I'm curious about using NextJS to fetch an API with a specific router ID. Can anyone provide guidance on how to achieve this and then render the data as HTML?

Greetings! I am currently coding in NextJS and working on a user page that fetches user-specific information from an API. My goal is to extract the ID query from the URL and use it to make an API request. The API endpoint follows this structure: /Users/{i ...

Tips for populating an HTML input with the value of a link element using JQuery

I have a form input that I want to populate with autocomplete suggestions from my database using Ajax. To style the list, I am using bootstrap 4, and I have opted to use the <a></a> tag instead of the <li></li> tag. This is because ...

Validate forms using jQuery with the power of ajax

Is there a way to effectively check for the existence of a username? I want to increment a variable called "form_error" if the username already exists. If "form_errors" is greater than 0, I need the code to stop and return false. However, when I use an Aj ...

Incorporating nested maps in JSX for efficient data manipulation

{normalizedData.map(item => <div key={item.display_date_numberic}> <div>{item.display_date_numberic}</div> </div> {!isEmpty(item.applicants) && item.applicants.map(applicant => <div className= ...

What steps should be taken to validate a condition prior to launching a NextJS application?

In my NextJS project (version 13.2.4), I usually start the app by running: npm run dev But there's a new requirement where I need to check for a specific condition before starting the app. If this condition is not met, the app should exit. The condi ...

What is the best way to make my JSON data trigger an alert when the button on my HTML page is clicked?

I've been working hard to display JSON data containing information about the school name, degree type, semester enrollment, courses, and student details. However, I'm facing an issue where nothing happens when I click the button linked to a click ...

Mouseover function ceases to function once an element is dropped

After referencing this discussion, I successfully managed to drag items from one scroll overflow to another. However, the issue arises when these items (or their clones) are in the other scroll overflow as they do not respond to .mouseover(). The goal is ...

Looking to extract a particular set of information from past records in a GAS web application

Regarding a previous query I made before (Check for login username and password, and then bring data from every previous entry). I've developed a web application to monitor the working hours of employees at my organization. The app is straightforward ...

Tips for utilizing an object key containing a dash ("-") within it

Here is an example of the object structure: { approved_for_syndication: 1 caption: "" copyright: "" media-metadata: (3) [{…}, {…}, {…}] subtype: "photo" } How can I properly a ...

How to retrieve data from a nested object within a JSON array using JavaScript

When I use Logger.log(response.data.phone), the following data is displayed in my log: [{label=work, primary=true, value=5558675309}, {label=work, value=6108287680, primary=false}, {value=6105516373, label=work, primary=false}] My goal is to have the two ...

Using Javascript to dynamically add and remove elements on click

Whenever I click on a link, I am able to generate input, label, and text. However, I want to be able to delete these elements with the next click event on the same link: I've tried updating my code like this: var addAnswer = (function() { var la ...

NodeJS/ExpressJS API exposure

Currently, I am developing a website using Express and implementing route handling with the help of express router. The routes I have set up so far include registration, login, upload, and more. One particular route, upload, requires files to be uploaded ...

Disregard any unnecessary lines when it comes to linting and formatting in VSC using EsLint and Prettier

some.JS.Code; //ignore this line from linting etc. ##Software will do some stuff here, but for JS it's an Error## hereGoesJs(); Is there a way to prevent a specific line from being considered during linting and formatting in Visual Studio Code? I h ...

Determine the quantity of items that meet specific criteria

The initial state of my store is set as follows: let initialState = { items: [], itemsCount: 0, completedCount: 0 }; Whenever I dispatch an action with the type ADD_ITEM, a new item gets added to the items array while also incrementing the count in ...

Preventing the page from scrolling to the top while utilizing an Angular-bootstrap modal and a window position:fixed workaround on an iPad

It's common knowledge that there is a bug in bootstrap modals on certain devices, causing the page behind the modal to scroll instead of the modal itself (http://getbootstrap.com/getting-started/#support-fixed-position-keyboards) An easy fix for this ...