考虑以下HTML5 + Javascript:
$(function() {
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
});
$('#edit input')
.keyup(function(e) {
if (e.keyCode == 13) { // <enter>
$('#value').show();
$('#edit').hide();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input type="text" value="hello" />
</div>
最初,所有这一切都是为了捕获文本hello
上的点击事件,用输入框替换文本。当用户点击 Enter 时,新文本将通过AJAX保存到服务器,输入框再次替换为文本。
现在我添加了a
标记,以便通过 Tab + 输入而不是仅使用鼠标进行导航(可访问性; yay!),但我发现,当这样做时,对focus()
的调用会神奇地触发keyup()
事件。 (我知道这一点,因为注释掉对focus()
的调用会导致所需的行为。)
结果是标签和输入文本打开但随后立即关闭input
框,就用户而言,根本没有发生任何事情。
为什么input
的{{1}}处理程序是由完全不相关的元素上的keyup
事件触发的?我怎样才能阻止这种情况发生?
click
hello
消失了;文本框出现,里面有插入符号hello
重新出现hello
成为焦点hello
消失了;文本框出现,里面有插入符号hello
再次出现......在我有机会做任何事之前。答案 0 :(得分:5)
所以问题是当你按下回车键时,释放密钥时会触发keyup
事件。
这会创建如下所示的流程: 1,点击链接(按回车键) 2,链接隐藏 3,重点放在文本输入上(此时仍然按下回车键) 4,释放密钥(keyup事件被触发)
如果您将事件更改为keydown
,则在链接上按Enter键不会与输入冲突,因为该输入没有焦点。
此外,在keyup事件中使用的keydown事件中使用相同的代码仍将执行完全相同的操作(即按Enter键和输入隐藏,链接显示)。
修改强>
https://jsfiddle.net/geyut7uv/
我能找到的唯一可靠的解决方案是创建一个&#34;拦截器&#34;变量&#34;禁用&#34; keydown事件。只有在点击了keydown时,我才将它附加到链接。这将通过输入检查keydown事件,如果用户按住该键,将立即触发该输入。
仅当触发输入键加密事件时才允许“阻止”&#34;变量传递。
理想情况下,我想删除所有全局范围变量,但我无法找到识别当前正在使用事件(keydown)的方法。
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input type="text" value="hello" />
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
var enter_enabled = true;
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
}).keydown(function(e){
enter_enabled = false;
});
$('#edit input')
.keydown(function(e){
if(e.keyCode == 13 && enter_enabled){
$('#value').show();
$('#edit').hide();
}
})
.keyup(function(e){
if(e.keyCode == 13){
enter_enabled = true;
}
});
});
</script>
答案 1 :(得分:4)
这是另一种解决方案。功能的唯一区别在于输入仅在释放时显示并聚焦。它会监听keydown
并阻止默认键盘点击,然后在keyup
事件中执行交换,以便keyup
不会进入输入字段。我已经在IE 11,Chrome和Firefox上试用了它,所有这些都在Windows上。
$(function() {
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
});
$('#value a')
.keydown(function(e) { // Prevent default enter click
if (e.keyCode == 13) {
e.preventDefault();
e.stopPropagation();
}
}).keyup(function(e) {
if (e.keyCode == 13) {
e.preventDefault();
e.stopPropagation();
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
}
});
$('#edit input')
.keyup(function(e) {
if (e.keyCode == 13) { // <enter>
$('#value').show();
$('#edit').hide();
}
});
});
答案 2 :(得分:2)
我走了使用旗帜updated fiddle-again的路线:
html保持不变,但js有所改变。我添加了一个'valueClicked'变量并将其设置为false;然后,使用它作为keyup中的条件,但是,在keyup条件检查之后,我重置了标志。
$(function() {
var valueClickedFromEnter = false;
$('#edit').hide();
function handleLinkClick(event)
{
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
valueClickedFromEnter =
(event.keyCode && event.keyCode == 13);
}
$('#value')
.css('cursor', 'pointer')
.keydown(handleLinkClick).click(handleLinkClick);
$('#edit input')
.keyup(function(e) {
if (e.keyCode == 13 && !valueClickedFromEnter) { // <enter>
$('#value').show();
$('#edit').hide();
}
valueClickedFromEnter = false;
});
});
这个想法是,无论何时从Tab键到锚点,输入标志,检查键盘然后重置标志,以便在下一次输入时条件通过。然后,正常使用它,永远不会设置标志,因此条件仍然通过。
编辑:根据反馈,clientX和clientY不是跨浏览器解决方案。相反,我使用中间函数来处理锚标记的keydown和click事件,并传递事件对象。然后检查该对象的keycode属性,如果它是13,则切换标志。
额外的好处是使用另一个键,如空格键,也会导致链接切换,如果用户开始输入,它将进入输入。
答案 3 :(得分:0)
更新以修复长按问题。问题很简单,你有一个事件正在侦听keyup,你特意把焦点放在那个元素上,所以它在用户释放密钥时触发。
更新#2: 这个应该完全有效,具有讽刺意味的是,我不得不扭转我的初始更改,以便在元素隐藏时执行所有操作。
试试这个:
var enterPressed = false;
var enteredExclusion = false;
$(document).ready(function() {
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#value').hide();
$('#edit').show();
$('#editabletext').focusin(function(e){
enteredExclusion = true;
}).focusout(function(e){
enterPressed = false;
enteredExclusion = false;
}).focus();
});
$('#editabletext')
.keydown(function(e){
if (e.keyCode == 13 && !enteredExclusion) { // <enter>
console.log('setting true');
enterPressed = true;
}
})
.keyup(function(e) {
enteredExclusion = false;
if (e.keyCode == 13 && (enterPressed )) {
$('#value').show();
$('#edit').hide();
console.log('setting false - keyup');
enterPressed = false;
}
});
});
HTML:
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input id="editabletext" type="text" value="hello" />
</div>
答案 4 :(得分:0)
我决定在不可见时禁用input
元素,而不是弄乱标志和诸如此类的东西。禁用的元素无法获得焦点,因此从理论上讲,您不会遇到一个问题,即当元素处于活动状态时,Enter键仍会出现。
当在input
元素中按下Enter键时,我还明确地将焦点设置为锚点。这可以确保在禁用它之前不再关注该元素,这可能会导致问题。
请注意,我只在Windows 8.1上测试过这个版本(哦,和FF 36和IE 11),所以YMMV。
$(function() {
$('#edit').hide();
var keyupHandler = function(e) {
if (e.keyCode === 13) { // <enter>
$('#value').show().focus();
$('#edit').hide().find('input').prop('disabled', true);
}
};
var clickHandler = function(e) {
$('#value').hide();
$('#edit').show(500, function() {
$(this).find('input').prop('disabled', false).focus();
});
e.preventDefault();
};
$('#value').on('click', clickHandler);
$('#edit').on('keydown', 'input', keyupHandler);
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input type="text" value="hello" />
</div>
&#13;
答案 5 :(得分:-1)
发生的事情似乎如下:
1)用户按下对焦元素的输入 - &gt;这将触发click事件以及keyup事件。点击事件首先被触发。
2)将调用点击#value
的处理程序。此处理程序显示#edit
字段并将焦点设置在此字段上。
3)触发keyup事件。但由于焦点现在位于#edit
,因此将触发此字段(!)
4)#edit
上的键盘处理程序将被调用并再次隐藏#edit
字段。