我有一个在Bootbox中创建的表单(它本身是Bootstrap模态之上的一层)。一旦创建,我就调用
$('#myForm').validate()
这种行为的可取之处在于,现在当用户浏览表单时,他们可以立即看到他们把其中一个字段搞砸了的反馈。在点击"选项卡"或单击其他位置之前输入了非电子邮件地址?警告和错误消息。太棒了
但不可取的是,模糊会吞噬其他事件。因此,如果用户选择点击"取消"(完全知道表单无效),则不会听到点击取消的声音,其处理程序也不会启动。第二次点击(现在焦点完全离开了窗体)并按预期取消激发。我不希望用户必须单击两次。
我看到了一种完全禁用模糊的技术,但随后上面描述的理想行为就消失了,这也是我不想要的。理想情况下,我想要的是"嗯,我模糊了,但我也知道用户在点击什么"。
[编辑以添加:]
我注意到这很令人困惑,所以让我尝试一种不同的方法来解决这个问题:是否有可能处理一个表单(上面调用了.validate()
),然后点击整个页面上的任何其他可点击项目,并成功启动其点击处理程序?
[再次编辑:]
根据Sparky的演示,我在模糊输入下方设置了一个警告。因此,要想看到问题在起作用,请启动这把小提琴:https://jsfiddle.net/bd1fhpu3/
然后单击其中一个输入字段,然后单击"仅一个按钮"。单击"只是一个按钮"的上部,以确保在释放鼠标按钮时,警告标签已将其从光标的热点中推出。
无论如何,这只是解释了问题是什么。解决它可能已经不在问题的范围内了,但它似乎值得分享,以防其他人遇到这个问题。要解决这个问题,我要么需要将Bootbox的点击事件覆盖为鼠标按下事件,而不是点击(然后你不需要按下和释放),要么我可以通过避免重新定位按钮来"创可贴"(tm)解决方案。也许是一个静态高度对话框,它足够高,可以容纳表单和任何可能的警告。这绝对有点像"黑客",因为你永远不知道以后是否会做其他事情,让问题再次出现。但这将是一个快速而简单的临时解决方案。
您不能使用内置的onfocuout
函数,因为JavaScript不可能知道聚焦到另一个字段和聚焦到取消按钮之间的区别。
您必须完全禁用onfocusout
并编写一些自定义事件处理程序。
您的代码是稀疏的,所以我的答案将是非常通用的。
$('#myForm').validate({
// other options here
onfocusout: false; // disable default blur event
});
然后编写一个事件处理程序,当它们关注input
时,该事件处理程序以编程方式触发对表单的验证,而当它们关注任何事情时(如取消按钮),则不执行任何操作。
$('#myForm input').on('focus', function() {
$('#myForm').valid(); // trigger validation on the form
});
然而,这将触发对整个表单的验证。如果你只想对失去焦点的一个字段触发验证,那么你就回到了原点,因为事件只知道焦点丢失了,而不知道它要去哪里。
为了子孙后代,这里有一个这样的"答案"。也许有一天它会帮助别人;你永远不会知道。
没有代码操作"不正确",因此既没有真正的修复程序,也没有代码示例可供提供。以下是发生的事情:
- 用户在字段中处于焦点
- 用户按下鼠标按钮(但释放操作尚未发生)
- 模糊事件触发,导致字段下方出现表单错误警告。这也产生了在屏幕Y轴上按下"取消"按钮的净效果
- 用户释放鼠标按钮,这通常会完成"点击"处理程序
然而,在#4中,由于"取消"按钮不再在光标下,绑定到该按钮的点击事件侦听器不会启动。
只要这个演示存在于互联网上,它就会在下面的评论中出现。然而,提供一个代码示例是毫无意义的。演示结束后,我将删除评论。
到目前为止我选择不追求的可能步骤(解决方法/黑客):
- 修改对话框,使鼠标按下事件触发时按钮不会移动,这意味着"点击"事件已成功完成
- 提供自定义代码,用鼠标按下事件代替按钮上的单击事件。然而,这会导致丢失相当常见的UI约定
- 强制用户按ESC取消,而不是单击按钮
- 如果你可以在错误消息上使用一些自定义样式,一个可能的选择是用
visibility: none
而不是display: non
e来隐藏它们。前者会隐藏文本,但仍然保留文本的垂直空间,而后者没有(因此你的模态正在扩展)。这将防止按钮在聚焦事件期间可能发生移动。您最终会得到额外的空白,但您可以通过删除表单组上的下边距来消除其中的一些空白(假设您正在使用它)
我相信还有其他解决办法,但这只是一个起点。