英文:
Close Search overlay only if inputs have no error
问题
我正在尝试开发一个全屏搜索字段,并希望橙色的“搜索”按钮只在所有输入都有效时关闭覆盖层。
每个输入限制为2位数,只能输入数字,范围在1到20之间。
除了最后一个输入有效时一切正常,即使前两个输入为空(错误),“搜索”按钮也会关闭覆盖层...
是否存在冲突或脚本错误?
$(function() {
$('a[href="#search"]').on("click", function(event) {
event.preventDefault();
$("#search").addClass("open");
$('#search > form > input[type="search"]').focus();
});
$("#search, #search button.close").on("click keyup", function(event) {
if (
event.target == this ||
event.target.className == "close" ||
event.keyCode == 27
) {
$(this).removeClass("open");
}
});
$(".send_btn").submit(function(event) {
event.preventDefault();
return false;
});
});
// 输入验证 - 如果不是有效输入则显示错误
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (
input.value < 0.9 ||
input.value > 20 ||
input.value.length === 1 ||
input.value.length === 0
) {
input.style.borderColor = 'red';
} else {
input.style.borderColor = '';
}
}
$('input').keypress(function(event) {
event = event || window.event;
var charCode = event.which || event.keyCode;
var charStr = String.fromCharCode(charCode);
if (event.key !== undefined && event.charCode === 0) {
return;
}
if (!/^([0-9])*$/.test(charStr)) {
event.preventDefault();
}
if (!/^[a-zA-Z0-9]+$/.test(charStr)) {
event.preventDefault();
}
});
// 如果输入为空,则禁用发送按钮 - 显示错误
$('.send_btn').click(function() {
$("input.each_item").each(function() {
if (this.value.trim().length === 0 || this.value.trim().length === 1 || this.value > 20)
$(this).css('border-color', 'red') &&
$('#search').addClass('open') &&
$('html').addClass("noScrollSimple");
else
$(this).css('border-color', '') &&
$('#search').removeClass('open') &&
$('html').removeClass("noScrollSimple");
});
});
html {
overflow-y: scroll;
}
body {
margin: 0px;
font-weight: 400;
font-size: 12px;
-webkit-font-smoothing: antialiased;
width: 100%;
min-width: auto;
background: #ebebeb;
padding: 50px;
}
.button {
width: 250px;
height: 50px;
color: #ebebeb;
background-color: cornflowerblue;
margin: 0 auto;
text-align: center;
font-size: 2.3em;
margin-top: 50px;
font-size: 2.3em;
cursor: pointer;
}
.input_cont {
display: inline-block;
width: 100%;
margin: 0px auto;
text-align: center;
max-width: 1250px;
}
.items {
display: flex;
flex: 1;
padding: 0px 20px 0px;
}
.each_item {
width: 100px;
height: 100px;
min-width: 100px;
min-height: 100px;
line-height: 2.75em;
margin: 0px auto;
display: table-cell;
float: left;
font-weight: bold;
color: #ebebeb;
font-size: 2.3em;
background: rgba(0, 0, 0, .6);
text-align: center;
-webkit-appearance: none;
}
#search {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: rgba(50, 50, 50, .9);
-webkit-transform: translate(-50%, -50%) scale(0, 0);
-moz-transform: translate(-50%, -50%) scale(0, 0);
-o-transform: translate(-50%, -50%) scale(0, 0);
-ms-transform: translate(-50%, -50%) scale(0, 0);
transform: translate(-50%, -50%) scale(0, 0);
opacity: 0;
}
#search input[type=search] {
color: #ebebeb;
background: rgba(0, 0, 0, 0);
font-weight: 300;
text-align: center;
border: 0px;
margin: 0px auto;
margin-top: -51px;
padding-left: 30px;
padding-right: 30px;
outline: none;
}
#search .btn {
background: chocolate;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
border: 0px solid transparent;
}
#search .close {
position: fixed;
top: 15px;
right: 15px;
opacity: 1;
width: 50px;
height: 50px;
}
#search .close:after {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(45deg);
left: 28px;
}
#search .close:before {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(-45deg);
left: 28px;
}
#search.open {
-webkit-transform: translate(-50%, -50%) scale(1, 1);
-moz-transform: translate(-50%, -50%) scale(1, 1);
-o-transform: translate(-50%, -50%) scale(1, 1);
-ms-transform: translate(-50%, -50%) scale(1, 1);
transform: translate(-50%, -50%) scale(1, 1);
opacity: 1;
}
#search,
#search.open {
-webkit-transition: all .35s;
-moz-transition: all .35s;
-ms-transition: all .35s;
<details>
<summary>英文:</summary>
I am trying to develop a full screen search field and would like the orange "search" button to close the overlay only if all inputs are valid.
Each input has a limit of 2 digits, only numbers and between 1 and 20.
Everything works fine except the "search" button closes the overlay when the last input is valid even if the first 2 inputs are left blank (error)....
Is there any conflict or is the script wrong?
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
$(function() {
$('a[href="#search"]').on("click", function(event) {
event.preventDefault();
$("#search").addClass("open");
$('#search > form > input[type="search"]').focus();
});
$("#search, #search button.close").on("click keyup", function(event) {
if (
event.target == this ||
event.target.className == "close" ||
event.keyCode == 27
) {
$(this).removeClass("open");
}
});
$(".send_btn").submit(function(event) {
event.preventDefault();
return false;
});
});
// validation input - error if not..
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (input.value < 0.9 || input.value > 20 || input.value.length === 1 || input.value.length === 0) {
input.style.borderColor = 'red';
} else {
input.style.borderColor = '';
}
}
$('input').keypress(function(event) {
event = event || window.event;
var charCode = event.which || event.keyCode;
var charStr = String.fromCharCode(charCode);
if (event.key !== undefined && event.charCode === 0) {
return;
}
if (!/^([0-9])*$/.test(charStr)) {
event.preventDefault();
}
if (!/^[a-zA-Z0-9]+$/.test(charStr)) {
event.preventDefault();
}
});
// If input is empty Send Button Click - error - no action
$('.send_btn').click(function() {
$("input.each_item").each(function() {
if (this.value.trim().length === 0 || this.value.trim().length === 1 || this.value > 20)
$(this).css('border-color', 'red') &&
$('#search').addClass('open') &&
$('html').addClass("noScrollSimple");
else
$(this).css('border-color', '') &&
$('#search').removeClass('open') &&
$('html').removeClass("noScrollSimple");
});
});
<!-- language: lang-css -->
html {
overflow-y: scroll;
}
body {
margin: 0px;
font-weight: 400;
font-size: 12px;
-webkit-font-smoothing: antialiased;
width: 100%;
min-width: auto;
background: #ebebeb;
padding: 50px;
}
.button {
width: 250px;
height: 50px;
color: #ebebeb;
background-color: cornflowerblue;
margin: 0 auto;
text-align: center;
font-size: 2.3em;
margin-top: 50px;
font-size: 2.3em;
cursor: pointer;
}
.input_cont {
display: inline-block;
width: 100%;
margin: 0px auto;
text-align: center;
max-width: 1250px;
}
.items {
display: flex;
flex: 1;
padding: 0px 20px 0px;
}
.each_item {
width: 100px;
height: 100px;
min-width: 100px;
min-height: 100px;
line-height: 2.75em;
margin: 0px auto;
display: table-cell;
float: left;
font-weight: bold;
color: #ebebeb;
font-size: 2.3em;
background: rgba(0, 0, 0, .6);
text-align: center;
-webkit-appearance: none;
}
#search {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: rgba(50, 50, 50, .9);
-webkit-transform: translate(-50%, -50%) scale(0, 0);
-moz-transform: translate(-50%, -50%) scale(0, 0);
-o-transform: translate(-50%, -50%) scale(0, 0);
-ms-transform: translate(-50%, -50%) scale(0, 0);
transform: translate(-50%, -50%) scale(0, 0);
opacity: 0;
}
#search input[type=search] {
color: #ebebeb;
background: rgba(0, 0, 0, 0);
font-weight: 300;
text-align: center;
border: 0px;
margin: 0px auto;
margin-top: -51px;
padding-left: 30px;
padding-right: 30px;
outline: none;
}
#search .btn {
background: chocolate;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
border: 0px solid transparent;
}
#search .close {
position: fixed;
top: 15px;
right: 15px;
opacity: 1;
width: 50px;
height: 50px;
}
#search .close:after {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(45deg);
left: 28px;
}
#search .close:before {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(-45deg);
left: 28px;
}
#search.open {
-webkit-transform: translate(-50%, -50%) scale(1, 1);
-moz-transform: translate(-50%, -50%) scale(1, 1);
-o-transform: translate(-50%, -50%) scale(1, 1);
-ms-transform: translate(-50%, -50%) scale(1, 1);
transform: translate(-50%, -50%) scale(1, 1);
opacity: 1;
}
#search,
#search.open {
-webkit-transition: all .35s;
-moz-transition: all .35s;
-ms-transition: all .35s;
-o-transition: all .35s;
transition: all .35s;
transition-property: initial;
transition-duration: 0.35s;
transition-timing-function: initial;
transition-delay: initial;
}
.search__input {
width: 100%;
height: 100%;
background: transparent;
outline: none;
color: #ebebeb;
transition: opacity 0s;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#search">
<div class="button">
Search</div>
</a>
<div id="search">
<div type="button" class="close"></div>
<div class="input_cont">
<div class="items">
<input name="num" type="text" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
<input name="num" type="text" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
<input name="num" type="text" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
</div>
</div>
<button type="submit" class="button btn btn-primary send_btn">Search</button>
</div>
<!-- end snippet -->
</details>
# 答案1
**得分**: 2
以下是您提供的代码的翻译:
首先,问题出在您逐个检查数值。因此,最后一个输入的数值才会生效。而且,您不应该添加 `type="text"` 然后检查输入是否包含除数字以外的任何内容。这是完全不必要的,只需将所有输入字段都添加 `type="number"`,它将只允许输入数字。大部分的代码只是在重复进行双重检查。
我已经清理了不必要的部分,现在它可以像您想要的那样正常工作。
以下是代码的翻译:
```html
<!-- 开始代码片段:js 隐藏:false 控制台:true Babel:null -->
<!-- 语言:lang-js -->
$(function() {
$('a[href="#search"]').on("click", function(event) {
event.preventDefault();
$("#search").addClass("open");
$('#search > form > input[type="search"]').focus();
});
$("#search, #search button.close").on("click keyup", function(event) {
if (
event.target == this ||
event.target.className == "close" ||
event.keyCode == 27
) {
$(this).removeClass("open");
}
});
$(".send_btn").submit(function(event) {
event.preventDefault();
return false;
});
});
// 添加返回语句
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (input.value < 0.9 || input.value > 20 || input.value.length === 1 || input.value.length === 0) {
input.style.borderColor = 'red';
return false;
} else {
input.style.borderColor = '';
return true;
}
}
// 验证每个输入字段的结果
$('.send_btn').click(function() {
var result = [];
$('.search__input').each(function() {
result.push(handleChange(this));
});
if (!result.includes(false)) { // 检查是否所有输入都有效
$('#search').removeClass('open');
$('html').removeClass("noScrollSimple");
}
});
<!-- 语言:lang-css -->
html {
overflow-y: scroll;
}
body {
margin: 0px;
font-weight: 400;
font-size: 12px;
-webkit-font-smoothing: antialiased;
width: 100%;
min-width: auto;
background: #ebebeb;
padding: 50px;
}
.button {
width: 250px;
height: 50px;
color: #ebebeb;
background-color: cornflowerblue;
margin: 0 auto;
text-align: center;
font-size: 2.3em;
margin-top: 50px;
font-size: 2.3em;
cursor: pointer;
}
.input_cont {
display: inline-block;
width: 100%;
margin: 0px auto;
text-align: center;
max-width: 1250px;
}
.items {
display: flex;
flex: 1;
padding: 0px 20px 0px;
}
.each_item {
width: 100px;
height: 100px;
min-width: 100px;
min-height: 100px;
line-height: 2.75em;
margin: 0px auto;
display: table-cell;
float: left;
font-weight: bold;
color: #ebebeb;
font-size: 2.3em;
background: rgba(0, 0, 0, .6);
text-align: center;
-webkit-appearance: none;
}
#search {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: rgba(50, 50, 50, .9);
-webkit-transform: translate(-50%, -50%) scale(0, 0);
-moz-transform: translate(-50%, -50%) scale(0, 0);
-o-transform: translate(-50%, -50%) scale(0, 0);
-ms-transform: translate(-50%, -50%) scale(0, 0);
transform: translate(-50%, -50%) scale(0, 0);
opacity: 0;
}
#search input[type=search] {
color: #ebebeb;
background: rgba(0, 0, 0, 0);
font-weight: 300;
text-align: center;
border: 0px;
margin: 0px auto;
margin-top: -51px;
padding-left: 30px;
padding-right: 30px;
outline: none;
}
#search .btn {
background: chocolate;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
border: 0px solid transparent;
}
#search .close {
position: fixed;
top: 15px;
right: 15px;
opacity: 1;
width: 50px;
height: 50px;
}
#search .close:after {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(45deg);
left: 28px;
}
#search .close:before {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(-45deg);
left: 28px;
}
#search.open {
-webkit-transform: translate(-50%, -50%) scale(1, 1);
-moz-transform: translate(-50%, -50%) scale(1, 1);
-o-transform: translate(-50%, -50%) scale(1, 1);
-ms-transform: translate(-50%, -50%) scale(1, 1);
transform: translate(-50%, -50%) scale(1, 1);
opacity: 1;
}
#search,
#search.open {
-webkit-transition: all .35s;
-moz-transition: all .35s;
-ms-transition: all .35s;
-o-transition: all .35s;
transition: all .35s;
transition-property: initial;
transition-duration: 0.35s;
transition-timing-function: initial;
transition-delay: initial;
}
.search__input {
width: 100%;
height: 100%;
background: transparent
<details>
<summary>英文:</summary>
First, the problem is because of you are checking the value one by one. So, in the end the last input's value is taking effect. And you should not add `type="text"` and then check if the input doesn't contains anything other than numbers. It is completely unnecessary, just add `type="number"` to all inputs and it will only allow numberical inputs. Most of the code is just doing double checks and same thing again and again.
I've cleaned up the unnecessary parts and now it is working very good like you wanted -
Here's the code
<!-- begin snippet: js hide: false console: true babel: null -->
<!-- language: lang-js -->
$(function() {
$('a[href="#search"]').on("click", function(event) {
event.preventDefault();
$("#search").addClass("open");
$('#search > form > input[type="search"]').focus();
});
$("#search, #search button.close").on("click keyup", function(event) {
if (
event.target == this ||
event.target.className == "close" ||
event.keyCode == 27
) {
$(this).removeClass("open");
}
});
$(".send_btn").submit(function(event) {
event.preventDefault();
return false;
});
});
// Added return statements
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (input.value < 0.9 || input.value > 20 || input.value.length === 1 || input.value.length === 0) {
input.style.borderColor = 'red';
return false;
} else {
input.style.borderColor = '';
return true;
}
}
// Verify results for each inputs
$('.send_btn').click(function() {
var result = [];
$('.search__input').each(function() {
result.push(handleChange(this));
});
if (!result.includes(false)) { // Check if all inputs are valid
$('#search').removeClass('open');
$('html').removeClass("noScrollSimple");
}
});
<!-- language: lang-css -->
html {
overflow-y: scroll;
}
body {
margin: 0px;
font-weight: 400;
font-size: 12px;
-webkit-font-smoothing: antialiased;
width: 100%;
min-width: auto;
background: #ebebeb;
padding: 50px;
}
.button {
width: 250px;
height: 50px;
color: #ebebeb;
background-color: cornflowerblue;
margin: 0 auto;
text-align: center;
font-size: 2.3em;
margin-top: 50px;
font-size: 2.3em;
cursor: pointer;
}
.input_cont {
display: inline-block;
width: 100%;
margin: 0px auto;
text-align: center;
max-width: 1250px;
}
.items {
display: flex;
flex: 1;
padding: 0px 20px 0px;
}
.each_item {
width: 100px;
height: 100px;
min-width: 100px;
min-height: 100px;
line-height: 2.75em;
margin: 0px auto;
display: table-cell;
float: left;
font-weight: bold;
color: #ebebeb;
font-size: 2.3em;
background: rgba(0, 0, 0, .6);
text-align: center;
-webkit-appearance: none;
}
#search {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: rgba(50, 50, 50, .9);
-webkit-transform: translate(-50%, -50%) scale(0, 0);
-moz-transform: translate(-50%, -50%) scale(0, 0);
-o-transform: translate(-50%, -50%) scale(0, 0);
-ms-transform: translate(-50%, -50%) scale(0, 0);
transform: translate(-50%, -50%) scale(0, 0);
opacity: 0;
}
#search input[type=search] {
color: #ebebeb;
background: rgba(0, 0, 0, 0);
font-weight: 300;
text-align: center;
border: 0px;
margin: 0px auto;
margin-top: -51px;
padding-left: 30px;
padding-right: 30px;
outline: none;
}
#search .btn {
background: chocolate;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
border: 0px solid transparent;
}
#search .close {
position: fixed;
top: 15px;
right: 15px;
opacity: 1;
width: 50px;
height: 50px;
}
#search .close:after {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(45deg);
left: 28px;
}
#search .close:before {
content: '';
height: 45px;
border-left: 5px solid #ebebeb;
position: absolute;
transform: rotate(-45deg);
left: 28px;
}
#search.open {
-webkit-transform: translate(-50%, -50%) scale(1, 1);
-moz-transform: translate(-50%, -50%) scale(1, 1);
-o-transform: translate(-50%, -50%) scale(1, 1);
-ms-transform: translate(-50%, -50%) scale(1, 1);
transform: translate(-50%, -50%) scale(1, 1);
opacity: 1;
}
#search,
#search.open {
-webkit-transition: all .35s;
-moz-transition: all .35s;
-ms-transition: all .35s;
-o-transition: all .35s;
transition: all .35s;
transition-property: initial;
transition-duration: 0.35s;
transition-timing-function: initial;
transition-delay: initial;
}
.search__input {
width: 100%;
height: 100%;
background: transparent;
outline: none;
color: #ebebeb;
transition: opacity 0s;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#search">
<div class="button">
Search</div>
</a>
<div id="search">
<div type="button" class="close"></div>
<div class="input_cont">
<div class="items">
<input name="num" type="number" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
<input name="num" type="number" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
<input name="num" type="number" min="1" max="20" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" class="search__input each_item" placeholder="00" />
</div>
</div>
<button type="submit" class="button btn btn-primary send_btn">Search</button>
</div>
<!-- end snippet -->
</details>
# 答案2
**得分**: 1
你正在为每个输入字段运行该函数,因此当最后一个字段有效时,它会隐藏覆盖层 - 这就是发生的事情。在循环外创建一个新变量,并使用它来跟踪任何输入字段是否无效,然后在循环之后使用该值来根据需要隐藏元素。
<details>
<summary>英文:</summary>
You are running the function for each input field, so when the last one is valid it would hide the overlay - which is what happens. Create a new variable outside the loop and use it to keep track if any of the input fields were invalid, then after the loop use the value to hide the element as needed.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论