javascript 当浏览器失去焦点时,Chrome(也许是 Safari?)在输入字段上触发两次“模糊”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9649966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chrome (maybe Safari?) fires "blur" twice on input fields when browser loses focus
提问by Pointy
Here is an interesting jsfiddle.
In Firefox:
在 Firefox 中:
- Run the fiddle
- Click in text input
- Click somewhere else. Should say "1 blurs".
- Click in the text input again.
- ALT-TABto another window. Fiddle should now say "2 blurs".
- 运行小提琴
- 单击文本输入
- 点击其他地方。应该说“1模糊”。
- 再次单击文本输入。
- ALT-TAB到另一个窗口。小提琴现在应该说“2模糊”。
In Chrome, at step 5, it says "3 blurs". Two separate "blur" events are fired when the whole browser loses focus. This is of interest because it means that it's not safe to assume, in a "blur" handler, that the element actually had focus just before the event was dispatched; that is, that the loss of focus — the transition from "being in focus" to "not being in focus" — is the reason for the event. When two"blur" events are generated, that condition is not satisfied during the handling of the second event, as the element is already not in focus.
在 Chrome 中,在第 5 步,它说“3 模糊”。当整个浏览器失去焦点时,会触发两个单独的“模糊”事件。这很有趣,因为这意味着在“模糊”处理程序中假设元素实际上在调度事件之前具有焦点是不安全的;也就是说,失去焦点——从“在焦点”到“不在焦点”的转变——是事件的原因。当生成两个“模糊”事件时,在处理第二个事件期间不满足该条件,因为该元素已经不在焦点上。
So is this just a bug? Is there a way to tell that a "blur" event is bogus?
那么这只是一个错误吗?有没有办法判断“模糊”事件是假的?
采纳答案by Fresheyeball
The reason it is firing twice is because of window.onblur. The window blurring triggers a blur event on all elements in that window as part of the way javascript's capturing/bubbling process. All you need to do is test the event target for being the window.
它触发两次的原因是因为 window.onblur。作为 javascript 捕获/冒泡过程的一部分,窗口模糊会在该窗口中的所有元素上触发模糊事件。您需要做的就是测试事件目标是否为窗口。
var blurCount = 0;
var isTargetWindow = false;
$(window).blur(function(e){
console.log(e.target);
isTargetWindow = true;
});
$(window).focus(function(){
isTargetWindow = false;
});
$('input').blur(function(e) {
if(!isTargetWindow){
$('div').text(++blurCount + ' blurs');
}
console.log(e.target);
});
回答by Chad Killingsworth
This is confirmed Chrome bug. See the Chromium Issue Tracker
这是已确认的 Chrome 错误。查看 Chromium 问题跟踪器
The workaround is in the accepted answer.
解决方法在已接受的答案中。
回答by Chad Killingsworth
Skip 2nd blur:
跳过第二个模糊:
var secondBlur = false;
this.onblur = function(){
if(secondBlur)return;
secondBlur = true;
//do whatever
}
this.onfocus = function(){
secondBlur = false;
//do whatever
}
回答by Ali Cheaito
I'm on Chrome Version 30.0.1599.101 m on Windows 7 and this issue appears to have been fixed.
我在 Windows 7 上使用 Chrome 版本 30.0.1599.101 m,这个问题似乎已得到修复。
回答by southpawlife
I am experiencing the same and the above posts make sense as to why. In my case I just wanted to know if at leastone blur event had occurred. As a result I found that just returning from my blur function solved my issue and prevented the subsequent event from firing.
我遇到了同样的情况,上面的帖子解释了为什么。就我而言,我只想知道是否至少发生了一个模糊事件。结果我发现刚从我的模糊函数返回就解决了我的问题并阻止了后续事件的触发。
function handleEditGroup(id) {
var groupLabelObject = $('#' + id);
var originalText = groupLabelObject.text();
groupLabelObject.attr('contenteditable', true)
.focus().blur(function () {
$(this).removeAttr('contenteditable');
$(this).text($(this).text().substr(0, 60));
if ($(this).text() != originalText) {
alert("Change Found");
return; //<--- Added this Return.
}
});
}
回答by Patrick
Looks like an oddity of angularjs gives a simpler solution when using ng-blur; the $event object is only defined if you pass it in:
当使用 ng-blur 时,看起来 angularjs 的一个奇怪之处提供了一个更简单的解决方案;$event 对象仅在您传入时才定义:
ng-blur="onBlur($event)"
so (if you aren't using ng-blur on the window) you can check for:
所以(如果你没有在窗口上使用 ng-blur)你可以检查:
$scope.onBlur = function( $event ) {
if (event != undefined) {
//this is the blur on the element
}
}
回答by Dagg Nabbit
This probably isn't what you want to hear, but the only way to do it seems to be to manually track whether the element is focused or not. For example (fiddle here):
这可能不是您想听到的,但唯一的方法似乎是手动跟踪元素是否获得焦点。例如(在这里小提琴):
var blurCount = 0;
document.getElementsByTagName('input')[0].onblur = function(e) {
if (!e) e = window.event;
console.log('blur', e);
if (!(e.target || e.srcElement)['data-focused']) return;
(e.target || e.srcElement)['data-focused'] = false;
document.getElementsByTagName('div')[0].innerHTML = (++blurCount + ' blurs');
};
document.getElementsByTagName('input')[0].onfocus = function(e) {
if (!e) e = window.event;
console.log('focus', e);
(e.target || e.srcElement)['data-focused'] = true;
};
Interestingly, I couldn't get this to work in jQuery (fiddle here) ... I really don't use jQuery much, maybe I'm doing something wrong here?
有趣的是,我不能让它在 jQuery 中工作(在这里小提琴)......我真的不怎么使用 jQuery,也许我在这里做错了什么?
var blurCount = 0;
$('input').blur(function(e) {
console.log('blur', e);
if (!(e.target || e.srcElement)['data-focused']) return;
(e.target || e.srcElement)['data-focused'] = false;
$('div').innerHTML = (++blurCount + ' blurs');
});
$('input').focus(function(e) {
console.log('focus', e);
(e.target || e.srcElement)['data-focused'] = true;
});
You could also try comparing the event's target with document.activeElement
. This example will ignore the alt+tab blur events, and the blur events resulting from clicking on Chrome's... chrome. This could be useful depending on the situation. If the user alt+tabs back into Chrome, it's as if the box never lost focus (fiddle).
您还可以尝试将事件的目标与document.activeElement
. 这个例子将忽略 alt+tab 模糊事件,以及点击 Chrome 的... chrome 产生的模糊事件。根据情况,这可能很有用。如果用户 alt+tabs 回到 Chrome,就好像框永远不会失去焦点(fiddle)。
var blurCount = 0;
document.getElementsByTagName('input')[0].onblur = function(e) {
if (!e) e = window.event;
console.log('blur', e, document.activeElement, (e.target || e.srcElement));
if ((e.target || e.srcElement) == document.activeElement) return;
document.getElementsByTagName('div')[0].innerHTML = (++blurCount + ' blurs');
};?
?