Mac OS X上的默认行为是单击复选框和按钮不会从具有焦点的其他控件(例如,文本框)中窃取焦点。我想在网上实现这一点。
我可以使用按钮和复选框本身,但不能用于复选框标签。
以此jsbin为例:
http://jsbin.com/kopateluze/1/edit?html,console,output
以下是表单的截图:
如果您首先关注文本框然后点击该按钮,则可以使用event.preventDefault()
上的mousedown
来防止文本框失去焦点。这很好用。如果你首先关注文本框,然后单击复选框,同样的事情就可以了。
但是,如果您首先关注文本框,然后点击复选框的label
文字,它就无法运作;文本框失去了焦点。
有没有办法阻止点击复选框label
从其他控件中窃取焦点?
纯JavaScript,请随时链接到库中实现的解决方案的源代码。
答案 0 :(得分:2)
好的,这是我能够弄清楚的事情,比事发后两年多一点。
首先,让我们谈谈推动这个问题的例子。当文本字段具有焦点时,我希望防止单击按钮来窃取焦点。我仍然希望调用任何按钮点击处理程序,我只是不想让焦点移动。
要做到这一点,我们只需要知道按钮会在mousedown
上得到关注,因此阻止它就像使用event.preventDefault()
一样简单:
<input placeholder="First focus me" type="text" />
<br/>
<button
onmousedown="event.preventDefault()"
onclick="console.log('button:click')">
Then click me
</button>
&#13;
请注意,单击该按钮会触发单击处理程序,但永远不会使该按钮获得焦点。另请注意,通过按Tab
按钮仍然可以获得焦点,因此这不会损害键盘访问。
事实证明,只要您使用没有标签的裸体复选框,这种技术就可以完美运行。
<input placeholder="First focus me" type="text" />
<br/>
<input
type="checkbox"
onmousedown="event.preventDefault()"
onclick="console.log('checkbox:click')"
/>
⇐ Then click the checkbox
&#13;
但是这确实存在可访问性问题,因为描述复选框的文本没有与之关联,复选框单击目标只是复选框本身,而不是随之而来的文本。这里的解决方案是添加label
元素,但这就是问题的起源。
<input placeholder="First focus me" type="text">
<br/>
<label>
<input type="checkbox"
onmousedown="event.preventDefault()"
onclick="console.log('checkbox:click')"
/>
Then click me
</label>
&#13;
如果单击复选框,则会成功阻止复选框窃取焦点。但是,如果单击复选框旁边的文本,则会从文本框中删除焦点。
关键在于了解label
元素如何与其关联的input
元素进行交互。 label
元素的click
处理程序实际上会被调用两次:event.target
是label
元素,而复选框就是{。}}。
因此,一般的解决方法是:
event.preventDefault()
上致电mousedown
。.click()
,但仅当event.target
等于label
元素时。
<input placeholder="First focus me" type="text" />
<br/>
<label for="checkbox"
onmousedown="event.preventDefault()"
onclick="
console.log('label:click');
if (this === event.target) {
console.log('label === event.target');
console.log('label:click preventDefault()');
// prevent focus and click
event.preventDefault();
// call click on the labeled control
this.control && this.control.click();
}
">
<input id="checkbox" type="checkbox"
onmousedown="event.preventDefault()"
onclick="
console.log('checkbox:click', `checked = ${this.checked}`);
"
/>
Then click me
</label>
&#13;