preventDefault在focus事件上不起作用。

6
我正在设计一个表单,如果它有某个类,则用户不应该能够与任何输入进行交互。由于各种原因,我想避免使用"disabled"属性。我试图阻止焦点事件的默认行为,但它不起作用。我在最近版本的Firefox、Chrome和Android中进行了测试。我尝试了各种事件组合,如"click change touchstart focus focusin"。我尝试在处理程序中放置"return false;"。是否有人知道这是为什么,以及如何使其工作?
<!DOCTYPE html>
<html><head>
<title>input test</title>
</head>
<body>
<form class="disabled">
  <input type="text">
</form>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(".disabled :input").bind("focus", function(e) {
  e.preventDefault();
});
</script>
</body></html>

您可以在http://jsfiddle.net/54Xka/上看到一个示例。
编辑:这将用于主要面向移动浏览器的站点。当模态对话框显示时,我计划禁用输入。模态对话框是使用我自己的代码实现的。它是一些非常简单的东西,可以显示和隐藏一个div。
编辑2:这是我现在的内容:
$(".disabled :input").live({
  focus: function() {
    $(this).blur();
  },
  change: function(e) {
    e.preventDefault();
  }
});

它有一些小的美观问题,但它可以工作。当我有更多时间时,我可能会尝试使用透明gif,或类似于jQuery UI对话框小部件的内容,或者实际上使用jQuery UI对话框小部件来实现对话框。

3个回答

7

对于文本字段,最好的做法是将其设置为只读。这样仍然可以进行 tab 键和复制操作,但不能进行修改。

<input type="text" readonly="readonly" value="Can't change me">

如果您想停止使用Tab键进行导航,那么一个正常运作的网页应该支持键盘导航,使其可以在页面对象之间进行切换。这意味着任何试图阻止焦点的选项都会干扰通过键盘导航来访问网页的任何尝试。因此,最好通过告诉浏览器该对象不是一个tab stop来阻止项目之间的Tab键切换,这样当按下Tab键时,浏览器会快乐地跳过它。您可以通过设置对象的tabIndex为-1来实现这一点。这样,键盘导航将永远不会停留在上面,但其他方面的功能将按预期工作。
<input type="text" readonly="readonly" tabIndex="-1" value="Can't change me or tab to me">

如果您使用的不是文本字段类型,则请更具体地说明使用的对象类型。在诉诸于干扰网页预期功能的脚本之前,应优先考虑支持您所需行为的HTML属性。如果您不希望用户与其交互,则还可以使用其他标记(如div)来仅显示数据,而非使用可编辑标记。
您可以在此处查看readonly和tabIndex字段的示例:http://jsfiddle.net/jfriend00/9wWkQ/ 现在,听起来我们有不断变化的规范。现在您甚至表示不希望他们能够选择文本。即使在一个不可编辑的普通div中也可以实现这一点。如果要阻止所有用户访问,包括单个字段文本的选择,则必须采用类似将空白透明gif图像放置在表单区域上方的方法。这将阻止所有鼠标与字段的交互,并结合readonly和tabIndex,也应该阻止所有键盘访问。

谢谢。我没有想到使用Tab键。readonly属性不是一个选项,因为我试图防止用户与表单交互。tabindex是我可以考虑的东西。 - Elias Zamaria
实际上,tabindex 属性本身并不是一个选项。用户仍然可以通过触摸选择输入。 - Elias Zamaria
如果你真的想要防止所有交互,我在上面的答案中添加了一个选项。只读属性可以防止更改所有项目。为什么这不是可取的解决方案的一部分呢? - jfriend00
我正在尝试实现一个模态对话框,它可以防止对话框以外的元素获得焦点。 - Elias Zamaria
2
然后,标准的做法是在整个页面上放置一个透明的gif图像(您可以缩放1x1图像以覆盖页面),并将对话框放在其上方。如果您在问题中提到了这一点,我们本可以更快地解决这个问题。 - jfriend00

5

您可以使用

this.blur();

...相反。


1
我会点赞你的回答,因为它很有帮助。但是,它有一些小的美观问题。在 iPhone 上,如果我点击一个输入框,屏幕上的键盘会出现一小段时间。这不是很糟糕,但有些分散注意力。在几个 Android 设备上,如果我尝试在密码输入框中输入,有时看起来好像已经聚焦了,但无法输入任何内容。在我的 Droid 2 上,它有一个物理键盘,按键会显示我输入的字符一小段时间,然后再改变回去。我希望能找到更好的解决方案,但如果找不到更好的解决方案,我可能会接受这个。 - Elias Zamaria
很遗憾,焦点事件无法被取消。您能解释一下为什么不想使用禁用属性吗? - Dr.Molle
我正在尝试避免使用禁用属性,因为它可能会很麻烦。当我显示对话框时,将不得不禁用所有输入。当隐藏对话框时,输入的禁用属性必须重置为其原始值(因为某些输入可能已经由于其他原因禁用)。因此,我需要一种记住禁用属性值的方法。这是我可以做到的,但可能需要更多的代码。我想知道是否有更简单和更优雅的方法。 - Elias Zamaria
1
我不确定这对你是否可行,但最简单的方法应该是隐藏整个表单。隐藏的元素无法获得焦点。 - Dr.Molle

5
你不能阻止默认行为,但你可以立即将焦点恢复到先前具有焦点的元素(这几乎与元素未接收焦点相同)。 这很容易做到,因为FocusEventrelatedTarget 属性包含引用到先前具有焦点的元素。
element.addEventListener('focus', (e) => {
  if (e.relatedTarget) {
    e.relatedTarget.focus();
  }
});


你的解决方案实际上帮助我防止下拉菜单抓取焦点到文本框外。该下拉菜单旨在从多个选项中选择文本,以插入光标所在的文本区域。谢谢! - Diego D
我不认为这是一个好的解决方案。与其仅仅使元素无法聚焦(从而在焦点顺序中被跳过),这个解决方案阻止了用户将焦点放在该元素上或者该元素之后的任何元素上。 - Max Patiiuk
@Max 这取决于你想要做什么。将元素设置为不可聚焦会将焦点转移到不可聚焦的父元素上,但我希望在点击按钮时忽略焦点效果,并将焦点恢复到之前拥有焦点的元素上。是的,我忘记添加tabIndex="-1"属性了,否则会破坏键盘导航功能。 - Maciej Krawczyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接