Как определить, где сосредоточиться?

Это было предложено здесь, но несколько лет назад, и в то время не было кросс-платформенного решения (кроме решения setTimeout, которое действительно не очень удобно).

Я хотел бы сделать onblur="foo(parm);" и иметь foo возможность определить, какой элемент теперь имеет фокус.

Я использую обычный javascript; нет jQuery для этого, пожалуйста.

Возможно ли это в наши дни?

Ответ 1

Вы можете попробовать что-то вроде этого:

function whereDidYouGo() {
    var all = document.getElementsByTagName('*');

        for (var i = 0; i < all.length; i++)
            if (all[i] === all[i].ownerDocument.activeElement)
                return all[i];
}

EDIT:

function whereDidYouGo() { return document.activeElement; }

Ответ 2

В jQuery в запросе OP:

$(':input').blur(function() {
    $focusedElement = $(':input:focus');
    //Do stuff with $focusedElement
}

Ответ 3

Интересный вопрос. В основе дела - когда срабатывает событие "фокус", до или после события размытия? Если он срабатывает перед событием размытия, проблема проста, потому что вы можете просто сохранить текущий фокус в переменной, доступной вашему событию размытия.

Однако, по крайней мере, в Chrome 13 появляется событие размывания перед событием фокуса. Одно из возможных решений.

Учитывая следующий HTML:

<input id="foo" value='foo' />
<input id="bar" value='bar' />

Вы можете:

var currentFocus;
var pendingBlur;

var foo = document.getElementById('foo');
foo.addEventListener('focus', function(){ 
    currentFocus = foo;
    if(pendingBlur !== undefined){
        pendingBlur();
        pendingBlur = undefined;
    }
});
foo.addEventListener('blur', function(){
    pendingBlur = function(){
        console.log('new focus:', currentFocus);
    };
});

var bar= document.getElementById('bar');
bar.addEventListener('focus', function(){ 
   currentFocus = bar;
   if(pendingBlur !== undefined){
        pendingBlur();
        pendingBlur = undefined;
   }
});
bar.addEventListener('blur', function(){
    pendingBlur = function(){
        console.log('new focus:', currentFocus);
    };
});

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

Ниже приведен рабочий рабочий пример на JSFiddle.

EDIT: это решение страдает от проблемы: если вы размываете форму, нажимая на что-то другое, кроме другого элемента формы, событие размытия никогда не срабатывает (так как мы ждем события фокуса). Единственный способ, который я могу себе представить, - использовать таймер, чтобы проверить, определено ли pendingBlur, и если да, вызовите его. В этот момент вам больше не нужно фокусное событие, чтобы вызвать обратный вызов размытия...