Различное поведение размытия в разных браузерах

Рассмотрим этот пример, где у меня есть 2 поля ввода:

<input id="a" />
<input id="b" style="display: none" />

И рассмотрим следующий JavaScript, который пытается сделать это:

Показывать #b только тогда, когда #a имеет фокус и скрывает #b, когда #a теряет фокус, кроме случаев, когда #a теряет фокус до #b.

$("#a").focus(function() {
    $("#b").show();
});

$("#a, #b").blur(function() {
    $("#b").hide();
});

$("#b").focus(function(){
    $("#b").show();
});

$("#a").focus(function() {
  $("#b").show();
});

$("#a, #b").blur(function() {
  $("#b").hide();
});

$("#b").focus(function() {
  $("#b").show();
});
#b {
  display: none;
}
<input id="a" value=a>
<input id="b" value=b>
<br/>^ focus on the input

Ответ 1

Как вы знаете, проблема в том, что разные браузеры выбирают вызов обработчиков событий в разных порядках. Одно из решений заключается в том, чтобы дать другим событиям возможность срабатывания, установив таймер на 0 миллисекунды, а затем проверив поля, чтобы увидеть, какая (если есть) сфокусирована.

a.onfocus = function() {show(b);};

a.onblur = function() {
    setTimeout(function() {
        //if neither filed is focused
        if(document.activeElement !== b && document.activeElement !== a){
            hide(b);
        }
            }, 0);
};

//same action as for a
b.onblur = a.onblur;

Протестировано в Chrome, Firefox, Internet Explorer и Safari. См. Полный рабочий пример (отредактированная версия вашей скрипки) в JSFiddle.net.

Ответ 2

Вы можете использовать экстраверсию, чтобы проверить, сфокусировано ли b, прежде чем скрыть b. Он работал в IE, Chrome и Firefox. У меня нет другого браузера. Вы можете проверить это.

var focusedB = false;
$("#a").focus(function(){
     $("#b").show();   
 });
 //if b is focused by pressing tab bar.
 $("#a").keydown(function(e){
     if(e.which === 9){
          focusedB = true;  
      }
   });
   $("#b").blur(function(){
        $("#b").hide();
   });
   $("#a").blur(function(){
       if(focusedB){
            focusedB = false;
        }else{
            $("#b").hide();
        }
    });
    $( "#b" ).mousedown(function() {
       focusedB = true;
    });

Ответ 3

Согласно этот архив whatwg.org:

Элемент может быть сфокусирован, если поведение по умолчанию для пользовательского агента позволяет он должен быть сфокусированным или если элемент специально ориентирован, но только если элемент либо отображается, либо является потомком холста элемент, представляющий встроенный контент.

Кажется, что все браузеры также не делают элементы ввода visibility:hidden и display:none ориентируемыми. Следующие JavaScript проверяют, в каких случаях элемент является настраиваемым.

function isFocusable(type) {
    var element = document.getElementById(type);
    result += type + ' is';
    try {
        element.focus();
        if (element != document.activeElement)
            result += ' not';
    } catch (e) {
      result += ' not (error thrown)';
    }
    result += ' focusable<br>';
}

var result = '';

function isFocusable(type) {
  var element = document.getElementById(type);
  result += type + ' is';
  try {
    element.focus();
    if (element != document.activeElement)
      result += ' not';
  } catch (e) {
    result += ' not (error thrown)';
  }
  result += ' focusable<br>';
}

isFocusable('text');
isFocusable('hidden');
isFocusable('disabled');
isFocusable('readonly');
isFocusable('visiblity-hidden');
isFocusable('display-none');
isFocusable('div-hidden');

document.getElementById('browser-version').innerHTML = navigator.userAgent;
document.getElementById('logger').innerHTML += result;
<input id=text type=""></input>
<input id=hidden type="hidden"></input>
<input id=disabled disabled></input>
<input id=readonly readonly></input>
<input id=visiblity-hidden style="visibility:hidden"></input>
<input id=display-none style="display:none"></input>
<div id=div-hidden sytle="visibility:hidden" tabindex=1>
  </input>

  <div id=browser-version></div>

  <div id=logger></div>