Подтвердить что ты не робот

Chrome (возможно, Safari?) Дважды "размывается" на поля ввода, когда браузер теряет фокус

Вот интересный jsfiddle.

В Firefox:

  • Запустите скрипт
  • Щелкните по текстовому вводу
  • Щелкните в другом месте. Должен сказать "1 размывает".
  • Нажмите снова на текстовый ввод.
  • ALT-TAB в другое окно. Теперь скрипка должна сказать "2 размытия".

В Chrome на шаге 5 указано "3 размытия". Два отдельных события "размытия" запускаются, когда весь браузер теряет фокус. Это представляет интерес, поскольку это означает, что небезопасно предполагать в обработчике размытия, что элемент фактически имел фокус непосредственно перед отправкой события; то есть, что потеря фокуса; переход от "находящегося в фокусе" к "не находящемуся в фокусе"; является причиной события. Когда генерируются два события "размытия" , это условие не выполняется во время обработки второго события, так как элемент уже не находится в фокусе.

Так это просто ошибка? Есть ли способ сказать, что событие "размытия" является фиктивным?

4b9b3361

Ответ 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
    }
}