在一个函数中单击我的 table 中的任何按钮时,如何打开带有表单的模式

How to open a modal with a form inside when any button within my table is clicked in one function

我在 div 中有一个模式,我想在单击 table 中的任何按钮时弹出。它将从 API 获取数据作为问题,表单供用户回答,它会显示正确或不正确,每个按钮在单击后都会显示它已 'used'。 table 有 5 列和 6 行,包括标题行。我正在尝试为此创建一个 onclick 函数。

       

          <tr>
            <td><button id="21" data-category="255">500</button></td>
            <td><button id="22" data-category="190">500</button></td>
            <td><button id="23" data-category="135">500</button></td>
            <td><button id="24" data-category="145">500</button></td>
            <td><button id="25" data-category="130">500</button></td>
          </tr>
        </table>
      </div>
      <div class="board">
        <!-- categories get injected here -->
     </div>
      <!-- answers container -->
      <div class="card-modal">
        <button type="button" class="open-modal" data-open="modal1">...</button>
        <div class=card-modal-inner>
          <button type="button" class="close" data-dismiss="modal">&times;</button>
           <h2 class="clue-text"><!-- clue gets added here --></h2>
           <form autocomplete="off">
              <input name="user-answer" type="text" />
              <button type="submit">Answer</button>
           </form>
           <div class="result">
              <p class="result_success">CORRECT</p>
              <p class="result_fail">INCORRECT</p>
              <p class="result_correct-answer">
                 The correct answer is <span class="result_correct-answer-text"><!--answer gets injected here--></span>
              </p>
           </div>
        </div>
     </div>
 </div>

这里是您发表评论后的编辑,以明确您想要做什么。

我做了代码,注释很深,你应该明白每一部分,为什么要写在上面。我尽量保持简单,不要太技术化,保持逻辑简单,不使用花哨的方法或属性,只是你作为初学者应该知道的基本知识。

我添加了一堆 console.log() 以便您能够了解发生了什么,以及何时,如果您要尝试代码。尽管评论非常清楚,而且逻辑self-explainatory。 不要犹豫,给我评论来解释一些事情,但我相信你会得到一切。我添加了一个小技巧,可以防止用户通过发送另一个答案作弊。

const tr = document.querySelector("#tr")
const trChildrens = Array.from(tr.children)
const modal = document.querySelector("#modal")
const answerInput = document.querySelector("#answerInput")
const answerButton = document.querySelector("#answerButton")
const result = document.querySelector("#result")
const isCorrect = document.querySelector("#isCorrect")

let modalToggle = false // We're setting it in the global scope in case you need to access it further on.
let answer = "" // Same reason, else we'd put it on the function scope, which would works in your case. Answer is empty per default.

// We will use forEach, which will apply the code for each entry of our array, see it as a for loop, and read about it if you don't know about it.
trChildrens.forEach(child => { 
  child.addEventListener("click", () => {
    console.log("Hey, I've been clicked, so I'll open up the modal!")
    modalToggle = !modalToggle  // We're putting modalToggle to what it's not currently: false if it's true, true if it's false.
    if(modalToggle) { // In the case of modalToggl to be set to true, we want to display the modal.
      modal.style.display = "block" // Replacing the display:none of the modal to the display:block to show it.
    }
  })
})


answerButton.addEventListener("click", answerCheck) // Simply execute answerCheck() when clicking the Answer button.

function answerCheck() {
 // When the answer button is clicked, we want to put the current value of the input as the answer.
 answer = answerInput.value // .value allows us to get the value of an input;
 answerButton.disabled = true  // Once the uesr press the "Answer" button, he shall not be allowed to do it again.
 answerButton.removeEventListener("click", answerCheck) // prevent people to use a trick where they would remove the disabled in DevTools, and resend answer to get it correct while they were not.
 
 // This will need to be coded with your API logic, I will code it with the logic in mind, you'll have to adapt.
 // At this point, you'll have to call your API to get the correct answer, store it in a variable and just use it in the if statement.
 if (answer != "This will be the result of the API") {
   console.log("The answer is different from the API result, the answer is not correct!")
   isCorrect.textContent = "incorrect"
 } else {
   console.log("The answer is corresponding to the API result, the answer is correct!")
   isCorrect.textContent = "correct"
 }
 result.textContent = "Your API result."
}

这是设置了 id 的代码的 HTML 部分。

<table>
    <tr id="tr">
        <td><button id="21" data-category="255">500</button></td>
        <td><button id="22" data-category="190">500</button></td>
        <td><button id="23" data-category="135">500</button></td>
        <td><button id="24" data-category="145">500</button></td>
        <td><button id="25" data-category="130">500</button></td>
    </tr>
</table>
</div>
<div class="board">
    <!-- categories get injected here -->
</div>
<!-- answers container -->
<div id="modal" class="card-modal" style="display: none;">
    <button type="button" class="open-modal" data-open="modal1">...</button>
    <div class=card-modal-inner>
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h2 class="clue-text">
            <!-- clue gets added here -->
        </h2>
        <form autocomplete="off">
            <input id="answerInput" name="user-answer" type="text" />
            <button id="answerButton" type="button">Answer</button>
        </form>
        <div class="result">
            <p class="result_correct-answer">
                The correct answer is <span id="result" class="result_correct-answer-text">
                    <!--answer gets injected here-->
                </span>. Your answer was <span id="isCorrect"></span>

            </p>
        </div>
    </div>
</div>

您所要做的就是 answerCheck() 函数末尾的 API 部分。将结果存储在一个变量中,只需将我的 "string" 替换为您的变量即可使其有意义。

到目前为止一切看起来都很好,我最大的问题是打开模式,一旦问题在表单中得到回答,它就会更新分数。我有点迷失在 javascript 模式中我实际上缺少什么,以便打开模式并显示从提交答案的表单获取的数据中的问题。

class GuessingTrivia {
  constructor(element, options = {}) {
    this.categoryIds = [255, 190, 135, 145, 130];
    // Default Categories pulled from https://jservice.io/search:
    // 3 letter words 255, movies 130,food and drink 190, mythology 135, nonfinction 145

    /*fetch this data from API */
    this.categories = { 255: [], 190: [], 135: [], 145: [], 130: [] };

    // Form elements
    this.formElement = document.querySelector(".form");
    this.gameBoardElement = document.querySelector(".table");
    this.scoreCountElement = document.querySelector(".score-count");

    const tr = document.querySelector("#tr");
    const trChildrens = Array.from(tr.children);
    const modal = document.querySelector("#modal");
    const answerInput = document.querySelector("#answerInput");
    const answerButton = document.querySelector("#answerButton");
    const result = document.querySelector("#result");
    const isCorrect = document.querySelector("#isCorrect");
  

  function getQuestionsByCategory(id) {
    const data = this.categories[id];
    return data.map((singleObject) => singleObject.question);
  
  initGame() {
    this.categoryIds.forEach((category) => this.fetchDataByCategory(category));
    // this.fetchCategories();
  }
}
}
}

const game = new GuessingTrivia(document.querySelector(".app"), {});
game.initGame();

const table = document.querySelector("table");
const tableBtns = table.querySelectorAll("button");
console.log(tableBtns);
tableBtns.forEach((btn) => {
  btn.addEventListener("click", (e) => {
    const category = e.target.dataset.category;
    const question = game.getQuestionsByCategory(category)[Number(id) + 1];
    console.log(question);
  });
});

// ID for this clue
const clueId = categoryIndex + "-" + index;
category.clues.push(clueId);

let modalToggle = false;
let answer = ""; // Answer is empty as default.

// applying the code for each entry of the array
trChildrens.forEach((child) => {
  child.addEventListener("click", () => {
    console.log("Button has been clicked,open up the modal");
    modalToggle = !modalToggle;
    if (modalToggle) {
      // display the modal if its true
      modal.style.display = "block";
    }
  });
});

answerButton.addEventListener("click", answerCheck); // check answer when clicking the Answer button

function answerCheck() {
  // adding the current value of the input as the answer when user types it in
  answer = answerInput.value;
  answerButton.disabled = true;
  answerButton.removeEventListener("click", answerCheck); //so  user cannot cheat

  // Calling API to get the correct answer
  async function fetchDataByCategory(id) {
    const response = await fetch(`https://jservice.io/api/category?id=${id}`);
    const data = await response.json();
    const answerCheck = data.answerCheck;
    this.categories[id] = [clues[0], clues[1], clues[2], clues[3], clues[4]];
    console.log(this.categories);
  }
  if (answer != "The result of the API") {
    console.log("answer is incorrect");
    isCorrect.textContent = "incorrect";
  } else {
    console.log("answer is correct!");
    isCorrect.textContent = "correct";
  }
  result.textContent = "API result.";
}

   // Score up update from 0 
   updateScore(change);
  this.score = 0;
  this.updateScore(0);
  this.score =+ change;
      this.scoreCountElement.textContent = this.score;
      this.updateScore(this.currentClue.value)


  this.clues[clueId] = {
    question: clue.question,
    answer: clue.answer,
    value: (index + 1) * 100
    };
* {
    box-sizing:border-box;
    margin: 0;
    padding: 0;
}


html {
    overflow-x:auto;
    overflow-y: auto;
    height: 100%;
    margin: auto;

}

.top-heading {
    display: flex;
    justify-content: space-between;
    align-items: center;

}

body {
    background-color:#2a3698;   
    height:100%;
    font-family:Verdana, Arial, Helvetica, sans-serif;
    font-size: 2vw;
    text-align:center;
    padding: 1em;
    /*overflow-y: hidden*/

}
table{
    border:3px solid;
    width: 100%;
    text-align: center;
    justify-content: space-around;
    border-radius: 5px;
    height: 40rem;
    position: relative;
    margin: auto;
    margin-bottom: 1em;
    padding: 5px;
    transition: .1s;
    z-index: 1;


}
button {
    background-color: #2a3698;
    border-style: bold;
    display:inline-block;
    height:100px;
    width: 185px;
    padding: 14px;
    font-size: 25px;
    font-weight: bold;
    box-shadow: 5px 10px;

}

th{
    justify-content: space-evenly;

}

th, td {
    padding-top: 10px;
    padding-bottom: 20px;
    padding-left: 30px;
    padding-right: 40px;
}
.score {
    color: green;
    font-size: 1em;
    margin-left: 0.2em;
    display: flex;
    align-items: center;
    font-weight: bold;
    font-family :Verdana, Arial, Helvetica, sans-serif;

}
.score-count{
    color:white;
}
/*table{
    visibility:hidden;
}

.card-modal {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s;
    position: fixed;
    align-items: center;
    justify-content: center;

}


.card-modal.visible {
    opacity: 1;
    pointer-events: initial;
}

.card-modal.showing-result .result {
    display: block;
}

.modal-container form {
    display: flex;
 }

 .modal-container form button[type="submit"] {
    padding-left: 2em;
    padding-right: 2em;
    cursor: pointer;
    font-family: inherit;
    background: var(--yellow);
    border: 0;
    font-size: inherit;
    border-top-right-radius: 0.4em;
    border-bottom-right-radius: 0.4em;
 }




.modal-container .clue-text {
    margin-bottom: 2em;
 }*/

 .modal-container {
     border:0;
     border-radius: 5px;
     box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
     padding: 10px 25px;
    position:fixed;
    top:0;
    left:0;
    height: 100vh;
    width: 200vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color:  rgba(0, 0, 0, 0.3);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s;

}

.modal {
    background-color: white;
    width: 800px;
    height: 600px;
    max-width: 100%;
    padding: 50px 50px;
    border-radius: 5px;
    text-align: center;
}

.modal h2 {
    margin: 0;
}

.modal p {
    font-size: 24px;
    opacity: 0.7;
}

.modal-container form {
    display: flex;
 }

 .modal-container .clue-text {
    margin-bottom: 2em;
 }

 .modal-container form button[type="submit"] {
    padding-left: 2em;
    padding-right: 2em;
    cursor: pointer;
    font-family: inherit;
    background: green;
    border: 0;
    font-size: inherit;
    border-top-right-radius: 0.4em;
    border-bottom-right-radius: 0.4em;
 }

 .result,
 .modal-container.showing-result form {
    display:none;
 }


 .modal-container .visible {
    opacity: 1;
    pointer-events: auto;
}

.modal-container .showing-result .result {
    display: block;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Jeopardy Game</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class="app">
      <!-- top header area for categories-->
      <header class="top-heading">
        <h1>Jeopardy Trivia</h1>
        <p class="score">Score <span class="score-count"> </span></p>
      </header>
      <div>
        <table>
          <th>
            <tr>
              <th>3 Letter Words</th>
              <th>Food & Drink</th>
              <th>Mythology</th>
              <th>Nonfiction</th>
              <th>Movies</th>
            </tr>
          </th>
          <tr id="tr">
            <td><button id="1" data-category="255">100</button></td>
            <td><button id="2" data-category="190">100</button></td>
            <td><button id="3" data-category="135">100</button></td>
            <td><button id="4" data-category="145">100</button></td>
            <td><button id="5" data-category="130">100</button></td>
          </tr>
          <tr id="tr">
            <td><button id="6" data-category="255">200</button></td>
            <td><button id="7" data-category="190">200</button></td>
            <td><button id="8" data-category="135">200</button></td>
            <td><button id="9" data-category="145">200</button></td>
            <td><button id="10" data-category="130">200</button></td>
          </tr>
          <tr id="tr">
            <td><button id="11" data-category="255">300</button></td>
            <td><button id="12" data-category="190">300</button></td>
            <td><button id="13" data-category="135">300</button></td>
            <td><button id="14" data-category="145">300</button></td>
            <td><button id="15" data-category="130">300</button></td>
          </tr>
          <tr id="tr">
            <td><button id="16" data-category="255">400</button></td>
            <td><button id="17" data-category="190">400</button></td>
            <td><button id="18" data-category="135">400</button></td>
            <td><button id="19" data-category="145">400</button></td>
            <td><button id="20" data-category="130">400</button></td>
          </tr>
          <tr id="tr">
            <td><button id="21" data-category="255">500</button></td>
            <td><button id="22" data-category="190">500</button></td>
            <td><button id="23" data-category="135">500</button></td>
            <td><button id="24" data-category="145">500</button></td>
            <td><button id="25" data-category="130">500</button></td>
          </tr>
        </table>
      </div>
      <div class="board">
        <!-- categories get injected here -->
    </div>
    <!-- answers container -->
    <div id="modal" class="card-modal" style="display: none;">
        <button type="button" class="open-modal" data-open="modal1">...</button>
        <div class=card-modal-inner>
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h2 class="clue-text">
                <!-- clue gets added here -->
            </h2>
            <form autocomplete="off">
                <input id="answerInput" name="user-answer" type="text" />
                <button id="answerButton" type="button">Answer</button>
            </form>
            <div class="result">
                <p class="result_correct-answer">
                    The correct answer is <span id="result" class="result_correct-answer-text">
                        <!--answer gets injected here-->
                    </span>. Your answer was <span id="isCorrect"></span>
    
                </p>
            </div>
        </div>
    <script src="index.js"></script>
  </body>
</html>