javascript - 有没有办法用 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()函数应该重置点击和默认行为。这是真的?
解决方案
这里已经有一个答案,但它没有解释为什么你的代码不起作用。从您的问题中可以清楚地看出您是在专门尝试理解问题,所以让我们解决它!:-)
您询问:
... off() 和 unbind() 函数应该重置点击和默认行为。这是真的?
在这种情况下,是的,这几乎就是发生的事情。更一般地说,off()
将删除一个事件处理程序。在这种情况下,它会删除click
添加到button
.
那么问题出在哪里?该按钮处理程序第一次运行时,它将自己从处理任何未来的点击中移除。这意味着您将永远无法再次显示搜索输入(这是处理程序通常所做的)。如果单击文档隐藏搜索输入,然后需要再次显示,则不能。执行此操作的处理程序不再监听您的按钮的点击!
让我们追踪这是如何发生的:
如果第二次点击是在文档上:
- 第一个处理程序不附加任何事件,不会触发;
- 第二个处理程序确实开火;
!$target.closest('#sSearch').length
将评估true
;$('#sSearch').not('.collapsed')
将评估true
- 测试通过,搜索字段被隐藏;
- 好的!这就是你想要的;
现在说你想再次显示搜索输入,所以你点击按钮:
- 第一个处理程序不附加任何事件,不会触发;
- 第二个处理程序确实开火;
!$target.closest('#sSearch').length
将评估false
;- 测试失败,第二个处理程序什么也不做;
- 两个处理程序都没有做任何事情,没有阻止默认操作 - 表单将提交,就像没有任何 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'); } });
推荐阅读
- r - 在 Rd 文件中保留空格
- arrays - 在 Julia 中按元组索引数组?
- java - 任务“:app:dataBindingMergeDependencyArtifactsDebug”执行失败
- mongodb - spring-data-mongodb 中的季度查询
- java - Spring 在 application.yml 中启用 SQL 日志
- java - 如何在 Firebase 中获取父节点
- java - Spring 应用程序中的两个实体管理器(Arrango 和 JPA)
- database - 使用 SQL 请求从数据库访问 QlikView 部分
- node.js - 操作 `users.findOne()` 缓冲 10000 毫秒后超时
- python - 当我将 cvs 导入 python 时,它只显示 1 号