如何隐藏提交按钮与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
相关产品推荐
相关产品推荐

