You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何隐藏提交按钮与carddata输入框且不影响JS交互

问题描述

我制作了一个Web表单,代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta name="robots" content="noindex">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
  <link href="./css/styles.css" rel="stylesheet">
  <script src="https://cdn.tailwindcss.com"></script>
  <script src="./js/cardreader.js"></script>
  <title>POSKick v1</title>
</head>

<body>
  <div class="container mx-auto p-4 h-full">
    <div class="flex justify-center h-full">
      <div class="max-w-[350px] w-full">
        <form action="/v1processpayment.php" method="POST">
          <div class="form-step active-step" id="step1">
            <h2 class="text-2xl text-center font-bold mb-4"> Order Info</h2>
            <label for="name">Order Amount:</label>
            <input type="text" id="amount" name="amount" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
            <br>
            <label for="name">Phone Number:</label>
            <input type="text" id="phone" name="phone" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
            <br>
            <label for="name">Zipcode:</label>
            <input type="text" id="zipcode" name="zipcode" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
            <input type="submit" id="submitButton" value="Submit" class="w-full mt-2 p-2.5 text-sm font-medium text-white bg-blue-600 rounded-md">

            <h2 class="text-2xl text-center font-bold mb-4"> Swipe Card</h2>

            <!--<label for="carddata">Card Data:</label>-->

            <button id="scanButton" class="w-full mt-2 p-2.5 text-sm font-medium text-white bg-blue-600 rounded-md">Capture Card</button>
            <div id="scanModal" class="modal">
              <div class="modal-content">
                <div class="spinner"></div>
                <p>Waiting for Customer...</p>
              </div>
            </div>
            <input type="password" id="carddata" name="carddata" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
          </div>
      </div>
    </div>
    </form>
</body>

</html>

我用JS捕获MSR读卡器的输入,把数据传入carddata输入字段,JS代码如下:

document.addEventListener("DOMContentLoaded", function() {
  const scanModal = document.getElementById("scanModal");
  const scanButton = document.getElementById("scanButton");
  const cardDataInput = document.getElementById("carddata");
  const form = document.querySelector("form"); // Select the form element
  let listeningForCardInput = false;
  let checkInterval;
  // Prevent the form from submitting
  form.addEventListener("submit", function(event) {
    if (listeningForCardInput) {
      event.preventDefault(); // Prevent the form from submitting
    }
  });
  // Show the modal and start listening for card input when the button is clicked
  scanButton.addEventListener("click", function() {
    scanModal.style.display = "block";
    listeningForCardInput = true;
    cardDataInput.focus(); // Automatically focus on the input for keyboard input
    // Check the input periodically with a short interval
    checkInterval = setInterval(checkAndCloseModal, 10); // Adjust the interval as needed
  });
  // Check if the card data is complete and close the modal
  function checkAndCloseModal() {
    const input = cardDataInput.value;
    if (input.endsWith("?")) {
      cardDataInput.value = input.trim(); // Remove leading/trailing spaces
      listeningForCardInput = false;
      scanModal.style.display = "none";
      clearInterval(checkInterval);
      // Automatically submit the form after the modal is closed
      submitForm();
    }
  }
  // Clear the interval when the modal is closed
  scanModal.addEventListener("click", function(event) {
    if (event.target === scanModal) {
      clearInterval(checkInterval);
      submitForm();
    }
  });
  // Function to submit the form
  function submitForm() {
    // Prevent further submissions
    form.removeEventListener("submit", preventSubmission);
    // Submit the form
    form.submit();
  }
  // Function to prevent form submission
  function preventSubmission(event) {
    event.preventDefault();
  }
  // Initially prevent form submission
  form.addEventListener("submit", preventSubmission);
});

现在遇到的问题:当我用display:none或者把输入框改成type="hidden"隐藏carddata字段时,模态框无法关闭,表单也提交不了;但字段可见时,JS能正常填充数据、关闭模态框并提交表单。

我需要实现的效果:

  • 隐藏提交按钮和carddata输入框
  • 保留原有功能:收银员点击「Capture Card」按钮,弹出模态框等待刷卡;客户刷卡后,读卡器模拟键盘输入数据,JS检测到输入以?结尾时,关闭模态框并提交表单

另外,当前是开发测试用,后续Amount、Phone、Zipcode会由POS系统自动填充,不会展示给收银员,最终表单只保留「Capture Card」按钮可见。

解决方案

问题核心是隐藏的输入框无法获取焦点,而原代码依赖cardDataInput.focus()让读卡器的输入流入字段。以下是两种可行方案:

方案一:视觉隐藏但保留输入框可交互性

不用display:none或type="hidden",改用CSS将输入框移出可视区域,但保留其可交互能力:

#carddata {
  position: absolute;
  left: -9999px;
  top: -9999px;
  opacity: 0;
}
#submitButton {
  display: none;
}
/* 同时隐藏不需要展示的Order Info区域 */
#step1 > h2:first-of-type,
#step1 > label,
#step1 > input:not(#carddata):not(#scanButton) {
  display: none;
}

这种方式下输入框依然能获取焦点,读卡器输入可正常写入,JS检测逻辑不受影响。

方案二:监听全局键盘事件,脱离输入框依赖

修改JS代码,直接捕获全局键盘输入,将数据暂存在变量中,最后赋值给隐藏字段:

第一步:修改HTML

将carddata改为隐藏字段,同时隐藏提交按钮和Order Info区域:

<div class="form-step active-step" id="step1">
  <!-- 隐藏Order Info区域 -->
  <div style="display: none;">
    <h2 class="text-2xl text-center font-bold mb-4"> Order Info</h2>
    <label for="name">Order Amount:</label>
    <input type="text" id="amount" name="amount" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
    <br>
    <label for="name">Phone Number:</label>
    <input type="text" id="phone" name="phone" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
    <br>
    <label for="name">Zipcode:</label>
    <input type="text" id="zipcode" name="zipcode" class="w-full px-3 py-2 mb-2 transition-all border border-gray-200 rounded-md outline-blue-600/50 hover:border-blue-600/30">
  </div>
  
  <h2 class="text-2xl text-center font-bold mb-4"> Swipe Card</h2>
  <button id="scanButton" class="w-full mt-2 p-2.5 text-sm font-medium text-white bg-blue-600 rounded-md">Capture Card</button>
  <div id="scanModal" class="modal">
    <div class="modal-content">
      <div class="spinner"></div>
      <p>Waiting for Customer...</p>
    </div>
  </div>
  <!-- 改为隐藏字段 -->
  <input type="hidden" id="carddata" name="carddata">
  <!-- 隐藏提交按钮 -->
  <input type="submit" id="submitButton" value="Submit" class="w-full mt-2 p-2.5 text-sm font-medium text-white bg-blue-600 rounded-md" style="display: none;">
</div>

第二步:修改JS代码

document.addEventListener("DOMContentLoaded", function() {
  const scanModal = document.getElementById("scanModal");
  const scanButton = document.getElementById("scanButton");
  const cardDataInput = document.getElementById("carddata");
  const form = document.querySelector("form");
  let listeningForCardInput = false;
  let checkInterval;
  let cardDataBuffer = ""; // 用变量暂存刷卡数据

  // 阻止初始表单提交
  form.addEventListener("submit", preventSubmission);

  scanButton.addEventListener("click", function() {
    scanModal.style.display = "block";
    listeningForCardInput = true;
    cardDataBuffer = ""; // 清空缓存
    // 监听全局键盘事件
    document.addEventListener("keydown", handleKeyInput);
    checkInterval = setInterval(checkAndCloseModal, 10);
  });

  function handleKeyInput(e) {
    if (!listeningForCardInput) return;
    // 将按键字符加入缓存
    cardDataBuffer += e.key;
  }

  function checkAndCloseModal() {
    if (cardDataBuffer.endsWith("?")) {
      const cleanedData = cardDataBuffer.trim();
      cardDataInput.value = cleanedData; // 赋值给隐藏字段
      listeningForCardInput = false;
      scanModal.style.display = "none";
      clearInterval(checkInterval);
      document.removeEventListener("keydown", handleKeyInput); // 移除监听
      submitForm();
    }
  }

  scanModal.addEventListener("click", function(event) {
    if (event.target === scanModal) {
      clearInterval(checkInterval);
      document.removeEventListener("keydown", handleKeyInput);
      submitForm();
    }
  });

  function submitForm() {
    form.removeEventListener("submit", preventSubmission);
    form.submit();
  }

  function preventSubmission(event) {
    event.preventDefault();
  }
});

这种方案完全脱离输入框的限制,更适合隐藏字段的场景。


内容的提问来源于stack exchange,提问作者David Desilets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 08:30:56