Chrome (возможно, Safari?) Дважды "размывается" на поля ввода, когда браузер теряет фокус
Вот интересный jsfiddle.
В Firefox:
- Запустите скрипт
- Щелкните по текстовому вводу
- Щелкните в другом месте. Должен сказать "1 размывает".
- Нажмите снова на текстовый ввод.
- ALT-TAB в другое окно. Теперь скрипка должна сказать "2 размытия".
В Chrome на шаге 5 указано "3 размытия". Два отдельных события "размытия" запускаются, когда весь браузер теряет фокус. Это представляет интерес, поскольку это означает, что небезопасно предполагать в обработчике размытия, что элемент фактически имел фокус непосредственно перед отправкой события; то есть, что потеря фокуса; переход от "находящегося в фокусе" к "не находящемуся в фокусе"; является причиной события. Когда генерируются два события "размытия" , это условие не выполняется во время обработки второго события, так как элемент уже не находится в фокусе.
Так это просто ошибка? Есть ли способ сказать, что событие "размытия" является фиктивным?
Ответы
Ответ 1
Причина, по которой она срабатывает дважды, вызвана 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);
});
http://jsfiddle.net/pDYsM/4/
Ответ 2
Это подтверждается ошибкой Chrome. См. Tracker Chromium Issue Tracker
Обходной путь находится в принятом ответе.
Ответ 3
Пропустить второе размытие:
var secondBlur = false;
this.onblur = function(){
if(secondBlur)return;
secondBlur = true;
//do whatever
}
this.onfocus = function(){
secondBlur = false;
//do whatever
}
Ответ 4
Это, вероятно, не то, что вы хотите услышать, но единственный способ сделать это - это вручную отслеживать, сфокусирован ли элемент или нет. Например (скрипка здесь):
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;
};
Интересно, что я не мог заставить это работать в 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;
});
Вы также можете попробовать сравнить цель события с document.activeElement
. В этом примере будут игнорироваться события размывания alt + tab и события размытия, возникающие при нажатии на Chrome... chrome. Это может быть полезно в зависимости от ситуации. Если пользователь alt + вставляет обратно в 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');
};
Ответ 5
Я использую Chrome версии 30.0.1599.101 m в Windows 7, и эта проблема, похоже, исправлена.
Ответ 6
Я испытываю то же самое, и вышеупомянутые сообщения имеют смысл, почему. В моем случае я просто хотел узнать, произошло ли хотя бы одно событие размытия. В результате я обнаружил, что только возврат из моей функции размытия решает мою проблему и предотвращает запуск последующего события.
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.
}
});
}
Ответ 7
Похоже, что странность угловых дает более простое решение при использовании ng-blur; объект $event определяется только в том случае, если вы передаете его:
ng-blur="onBlur($event)"
поэтому (если вы не используете ng-blur в окне), вы можете проверить:
$scope.onBlur = function( $event ) {
if (event != undefined) {
//this is the blur on the element
}
}