我有一个带有输入(子)的主div(父)和另外2个子div(可点击)。
我想捕获主要div的焦点输出事件 - 而不是在点击或聚焦输入或其他2个可点击的div时。我已经使用jQuery设置了一个事件处理程序来捕获所有元素上的focusin focusout事件。
当我点击输入
时,我看到的是什么如果我点击任何其他可点击的div
点击其他可点击的div时,我不希望主div失去焦点。
我怎样才能实现这一目标?我想在松散焦点上验证输入,但是在点击其他div时不能验证
到目前为止,这就是我所拥有的:Fiddle
HTML:
<div id="main">
<input id="i" type="text" />
<div id="Div2" class="icons" style="background-color:blue; right: 25px;" onclick="log('Clear Clicked');"></div>
<div id="Div1" class="icons" style="background-color:red;" onclick="log('DD Clicked');"></div>
</div>
CSS:
* {
-webkit-box-sizing: border-box;
/* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box;
/* Firefox, other Gecko */
box-sizing: border-box;
/* Opera/IE 8+ */
}
#main {
top: 50px;
left: 200px;
position: absolute;
border: 1px solid #00bfff;
width: 250px;
height: 27px;
}
input {
border: none;
width: 248px;
height: 25px;
position: absolute;
z-index: 200;
}
.icons {
text-align:center;
border:1px solid blue;
height: 23px;
width: 23px;
position: absolute;
top: 2px;
right: 2px;
z-index: 99999999999999999999999;
background-position: center;
background-repeat: no-repeat;
}
jQuery:
$("#main").focusin(function () {
log("Main div got focused");
});
$("#i").focusin(function () {
log("input got focused");
});
$("#Div2").focusin(function () {
log("dropdown div got focused");
});
$("#Div1").focusin(function () {
log("clear div got focused");
});
$("#main").focusout(function () {
log("Main div lost focused");
});
$("#i").focusout(function () {
log("input lost focused");
});
$("#Div2").focusout(function () {
log("dropdown div lost focused");
});
$("#Div1").focusout(function () {
log("clear div lost focused");
});
function log(msg) {
//window.console.log(msg);
$("body").append("<p>" + msg + "</p>");
}
任何帮助或指导赞赏
答案 0 :(得分:17)
这是一个最好的解决方法,因为我也有同样的问题^ _ ^
有一个事件的attr:“relatedTarget”
relatedTarget将提供此事件的下一个元素
因此,如果下一个元素不是你的盒子或盒子里的任何东西,那么就会引发焦点。
但是首先你必须让你的<div>
元素可以集中,你必须像这样在div上添加tabindex =' - 1'
<div id="main" tabindex='-1'>
脚本很简短:
$("#main, #main *").blur(function(e){
if(!$(e.relatedTarget).is("#main, #main *")){
//focus out.
}
});
焦点会丢失并进入#main,但是当你从#main区域丢失焦点时,你可以做任何事情。
这与您的要求略有不同,但我想这可能就是您想要的。 如果是这样,代码将非常干净。
答案 1 :(得分:1)
好的,所以看起来你正在构建某种输入小部件。我看到#main
div是小部件的外部容器,输入用于输入文本,然后你有两个其他div作为按钮或其他东西。您希望在用户尝试退出窗口小部件时验证输入的值,并且您试图通过在focusout
上侦听#main
来捕获此事件。这不起作用,因为div
不是可以获得焦点的元素。请参阅答案here了解更多信息。
我可以向你证明你的div不适合进行一些小实验:
如果您在e.stopPropagation()
和focusin
听众中加入focusout
作为输入,您会看到您的主要div实际上从未实际关注或未关注本身;它刚收到focusin
和focusup
事件,因为它们从您的输入中冒出DOM树。
所以,这意味着我们必须从另一个角度解决你的问题。
让我们用简短的用户故事描述你的小部件失去焦点意味着什么:
#main
/ #Div1
/ #Div2
- 小部件获得焦点#main
上的某处 - 小部件焦点不会丢失#Div1
,然后#Div2
- 小工具焦点不会丢失我们现在确切知道哪些状态应该导致验证运行。
首先,让我们用布尔变量跟踪小部件的“焦点”状态:
var isFocused = false;
小部件从未聚焦状态开始,当#main
或其子级中的任何位置发生单击或者输入以某种方式聚焦时(可以通过选项卡进入)用键盘):
$("#main").on('click',function(){
isFocused = true;
});
$("#i").on('focus',function(){
isFocused = true;
});
小部件变得不专心的唯一时间是a)它的焦点和b)用户点击页面上的其他位置:
$(document).on('click',function(){
if(isFocused){
isFocused = false;
//kick-off the validation check!
}
});
但是,由于默认情况下所有事件都会冒出DOM树,#main
内的多次点击会冒出document.body
并触发验证检查。为防止这种情况发生,我们在stopPropagation
的点击处理程序中点击事件调用#main
:
$("#main").on('click',function(e){
isFocused = true;
e.stopPropagation();
});
就是这样!
我希望我对你所追求的事情是正确的。
这是一个带有上述代码的working fiddle。
答案 2 :(得分:0)
这是一种简单的方法(据我所知)
$('#Div1').click(function(){
log('Clear Clicked');
//$('#main').focusin();
$('#i').focus();
});
$('#Div2').click(function(){
log('DD Clicked');
//$('#main').focusin();
$('#i').focus();
});
这里是fiddle
答案 3 :(得分:0)
基于此接受的答案Is there a way to use event.preventDefault with focusOut? If not, why?
$(document).on('mousedown', function (event) {
target = event.target;
main = document.getElementById("main");
input = document.getElementById("i");
if (target == input) return true;
parent = event.target.parentNode;
if (parent == main) {
event.preventDefault(); //prevent default DOM action
event.stopPropagation(); //stop bubbling
return false; // return
}
});
答案 4 :(得分:0)
另一种解决方法是在运行focusout handler之前添加一个小的setTimeout。
您可以轻松地将要排除的元素列表列入白名单,并在获得焦点时将其与clearTimeout排除。