我有一个<input>
和一个<button>
。
输入有一个onblur
事件处理程序,(有时)会导致<button>
被移动;如果将焦点放在<input>
上,用户去单击<button>
(因此在单击完成之前它从指针下方移动),他们当前必须将指针移动到按钮的新位置并再次单击它。 这种体验是次优的。
我希望用户只需单击<button>
一次(但必须保留<input>
失去焦点时按钮移动的功能)。 但是,如果用户在鼠标悬停之前将鼠标悬停在按钮上,然后将鼠标指针移开(包括从应用程序切换焦点),则不应触发任何单击事件(正常情况)。
我看不到任何基于处理onmousedown
和/或onmouseup
的方法在某些边缘情况下不容易出错。 我所能想到的就是在onblur
处理程序中强行移动光标,以便单击完成(如果确实会?——但这可能也是一个糟糕的用户体验。
如何最好地处理这个问题?
$('button').click(
$('<li><input></li>')
.children('input')
.blur(function(){
if (!this.value.length)
this.parentElement.remove();
})
.end(),
function(e){
e.data.clone(true)
.appendTo($(this).data('target'))
.children('input')
.focus();
}
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>
一种方法是在一秒钟而不是立即淡出元素的过程中淡出元素,这让用户有时间在按钮移动之前完成单击:
$(this.parentElement).fadeOut("slow", function() {
$(this).remove();
});
现场示例:
$('button').click(
$('<li><input></li>')
.children('input')
.blur(function(){
if (!this.value.length)
$(this.parentElement).fadeOut("slow", function() {
$(this).remove();
});
})
.end(),
function(e){
e.data.clone(true)
.appendTo($(this).data('target'))
.children('input')
.focus();
}
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>
也就是说,我想我会尝试找到一种方法,使列表元素之间的空间根本不改变,因为这仍然意味着事情会移动,只是在不同的时间 -希望在某个时候用户不会受到它的困扰,但是......不过,在这种情况下很棘手,因为列表彼此 重叠——第二个列表会在某个时候移动。如果您总是有一个输入框供用户输入,那么第二个列表将在不同的时间移动(当框中确实有一个值并且您为下一个值添加新的空白值时)。可以使用固定的列表大小和滚动来完成,但这取决于整体设计。
我有一个相关的问题,即我正在设置按钮样式以在按下时缩小,使用:active
伪类在鼠标按下时调整按钮大小,并在按钮获得焦点时重置其大小:focus
伪类。但是,如果单击按钮足够靠近其边缘,它仍会被激活并缩小,但光标现在刚好在按钮的边界之外,并且按钮将不再获得焦点。
这是点击事件本身工作方式的结果。对于要在给定element
上触发onclick
事件,光标必须"在[光标]位于元素内部时同时按下和释放"。 但是,如果光标在释放之前移动到元素之外,则会在包含这两个元素的"最具体的祖先元素"上触发该事件。具体而言,这会导致在element
上触发mousedown
事件,在其ancestor element
上触发mouseup
事件。
因此,解决方案是监视按钮的mousedown
事件,并在触发其父级mouseup
事件时单击该按钮(即,光标被按下在按钮上,但在其父级上释放)。
香草JS代码:
// The CSS selector for the buttons to monitor
const selectors = "button";
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll(selectors).forEach(button => {
// Watch for button press
button.addEventListener('mousedown', event => {
// The button is the event's original target
const element = event.target;
// Click if the cursor is released over the button's parent
element.parentElement.addEventListener('mouseup', () => {
element.click();
}, { once: true });
});
});
});
如果按钮的父级大小与按钮的大小相同(例如使用width: fit-content
),则此方法效果最佳。否则,如果光标释放在远离按钮的位置,但仍位于按钮的父元素上,则可能会发生意外单击。