有没有办法用jQuery切换提交按钮的行为?(例如显示/隐藏/提交)



我正试图切换一个按钮,根据用户是否单击文档来隐藏/折叠输入字段,选择点击提交还是显示输入字段。问题是,在用户取消输入字段后,提交按钮不会返回到切换行为;单击该按钮可再次打开表单提交中的输入字段结果。

单击该按钮时,我需要触发一个搜索字段滑入。一旦输入字段可见,该按钮将提交而不是切换,除非用户单击文档以隐藏字段。目前,最初的点击会打开输入字段,点击文档会折叠字段。在上一个操作之后的第二次单击将导致"提交"。

我相信,基于我的一点理解,preventDefault()函数没有在第二次点击时发生,或者

.off('click')HTML:

<form action="" id="sSearch" class="collapsed">
<input type="search" id="sSearch-Field" placeholder="Search">
<button type="submit">
Open
</button>
</form>

JS:

$('#sSearch button').click(function (event) {
event.preventDefault();
$('#sSearch').removeClass('collapsed');
$('#sSearch button').off('click');
});
$(document).click(function (event) {
$target = $(event.target);
if(!$target.closest('#sSearch').length && $('#sSearch').not('.collapsed')) {
$('#sSearch').addClass('collapsed');
}
});

我不明白为什么preventDefault()函数在第二次点击时不起作用?根据我在类似问题中看到的内容,off()unbind()函数应该重置点击和默认行为。这是真的吗?

CodePen示例

这里已经有了答案,但它并不能解释为什么您的代码不起作用。从你的问题来看,很明显你是在专门试图理解这个问题,所以让我们来解决它!:-)

你问:

。。。ff()和unbind()函数应该重置点击和默认行为。这是真的吗?

在这种情况下,是的,几乎就是这样。更一般地说,off()将删除一个事件处理程序。在这种情况下,它将删除添加到buttonclick处理程序。

那么问题出在哪里呢?按钮处理程序第一次运行时,它将不再处理将来的任何单击。这意味着您将永远无法再次显示搜索输入(这是处理程序通常所做的)。如果您单击文档以隐藏搜索输入,然后需要再次显示,则不能。执行此操作的处理程序不再侦听您的按钮上的单击!

让我们追踪一下这种情况是如何发生的:

  • 如果第二次点击是在文档上:

    • 第一个处理程序没有附加到任何事件,不会激发
    • 第二个处理者开火
    • !$target.closest('#sSearch').length将评估true
    • $('#sSearch').not('.collapsed')将评估true
    • 测试通过,搜索字段被隐藏
    • 很好!这就是你想要的
  • 现在说你想再次显示搜索输入,所以你点击按钮:

    • 第一个处理程序没有附加到任何事件,不会激发
    • 第二个处理者开火
    • CCD_ 8将评估CCD_ 9
    • 测试失败,第二个处理程序什么也不做
    • 两个处理程序都没有做任何事情,默认操作没有被阻止——表单将提交,就像一个没有任何Javascript的普通HTML表单一样
    • 糟糕!你这不是你想要的

附带说明:$('#sSearch').not('.collapsed')有效,但为了可读性和一致性,它可能应该是$('#sSearch').not('.collapsed').length,就像第一个条件一样。

那么,如何获得你想要的行为呢?

为了坚持您正在使用的方法,当搜索字段被隐藏时,您需要重新附加第一个事件处理程序,以便页面返回到初始状态,就像页面加载时一样。

要做到这一点,我会将代码提取到一个函数中,这样你就可以从两个地方调用它,以避免重复:

// New function we can call whenever we need it
function showSearch (event) {
event.preventDefault();
$('#sSearch').removeClass('collapsed');
$('#sSearch button').off('click');
}
// Call our function when button clicked
$('#sSearch button').click(showSearch);
$(document).click(function (event) {
$target = $(event.target);
if(!$target.closest('#sSearch').length && $('#sSearch').not('.collapsed')) {
$('#sSearch').addClass('collapsed');
// Re-attach the function to button clicks, so page goes back to
// the initial state, before any button clicks
$('#sSearch button').click(showSearch);
}
});

这是一个正在工作的JSFiddle(很抱歉我从CodePen换了过来,我更习惯了)。

或者,虽然你采取的方法很好,但我可能会选择更简单的方法。与其根据用户活动添加或删除事件处理程序,我更愿意跟踪表单的当前状态,并使用它来确定单击时该做什么。

我们需要某种变量来跟踪状态。。。但如果你退一步,你已经有了这样一个变量!collapsed类告诉我们页面的当前状态。您可以使用jQuery的.hasClass()方法来检查类是否存在,这将告诉我们页面当前的状态:

  • 单击按钮时,如果输入当前具有collapsed类,则需要显示它,因此可以阻止提交并删除该类。如果输入没有该类,则不执行任何操作,并允许提交。

    $('#sSearch button').on('click', function(event) {
    if ($('#sSearch').hasClass('collapsed')) {
    event.preventDefault();
    $('#sSearch').removeClass('collapsed');
    }
    });
    
  • 如果单击按钮上的而不是,当显示输入时,您希望将其隐藏;当输入被隐藏时,你什么也不做。

    $(document).on('click', function (event) {
    $target = $(event.target);
    if(!$target.closest('#sSearch').length && !$('#sSearch').hasClass('collapsed')) {
    $('#sSearch').addClass('collapsed');
    }
    });
    

这是另一个使用这种不同方法的JSFiddle。

您可以添加一个标志变量来确定是否显示输入。此外,您需要使用。CCD_ 15而不是CCD_ 16来处理实时更改。

这是代码:

let readySubmit = false;
$('#sSearch').on("click", "button", function(event) {
if (readySubmit == false) {
event.preventDefault();
$('#sSearch').removeClass('collapsed');
$('#sSearch button').off('click');
$('#sSearch button').html("Submit");
		
		readySubmit = true;
}
});
$(document).click(function(event) {
$target = $(event.target);
if (!$target.closest('#sSearch').length && $('#sSearch').not('.collapsed')) {
$('#sSearch').addClass('collapsed');
$('#sSearch button').html("Open");
		
		readySubmit = false;
}
});
#sSearch input {
position: absolute;
right: 40px;
width: 167px;
height: 38px;
padding-left: 0.75rem;
padding-right: 0.75rem;
border: 1px solid #ced4da;
transition-property: width, height, padding-left, padding-right;
transition-duration: 0.25s;
transition-timing-function: linear;
}
button {
transition: all 0.25s linear;
}
#sSearch.collapsed input {
width: 0;
padding-left: 0;
padding-right: 0;
border: none;
transition: all 0.25s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="" id="sSearch" class="collapsed">
<input type="search" id="sSearch-Field" placeholder="Search">
<button type="submit">
Open
</button>
</form>

最新更新