Когда происходит событие «размытия», как я могу узнать, на какой фокус элемента * направлено *? - PullRequest
160 голосов
/ 23 сентября 2008

Предположим, я прикрепил функцию blur к полю ввода HTML, например:

<input id="myInput" onblur="function() { ... }"></input>

Есть ли способ получить идентификатор элемента, который вызвал событие blur (элемент, по которому щелкнули) внутри функции? Как?

Например, предположим, что у меня есть такой промежуток:

<span id="mySpan">Hello World</span>

Если я щелкну промежуток сразу после того, как элемент ввода будет в фокусе, элемент ввода потеряет фокус. Как функция узнает, что на нее нажали mySpan?

PS: Если событие onclick диапазона будет происходить до события onblur входного элемента, моя проблема будет решена, потому что я мог бы установить некоторое значение состояния, указывающее на нажатие определенного элемента.

PPS: фон этой проблемы заключается в том, что я хочу, чтобы элемент управления автозаполнения AJAX был запущен извне (из интерактивного элемента), чтобы показать его предложения, без немедленного исчезновения предложений из-за события blur в элементе ввода. Поэтому я хочу проверить в функции blur, был ли нажат один конкретный элемент, и если это так, игнорировать событие размытия.

Ответы [ 23 ]

81 голосов
/ 23 сентября 2008

Хмм ... В Firefox вы можете использовать explicitOriginalTarget, чтобы вытащить элемент, по которому щелкнули. Я ожидал, что toElement сделает то же самое для IE, но, похоже, он не работает ... Однако вы можете извлечь недавно сфокусированный элемент из документа:

function showBlur(ev)
{
   var target = ev.explicitOriginalTarget||document.activeElement;
   document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
}

...

<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />

Предупреждение: Этот метод не работает для изменений фокуса, вызванных вкладкой через поля с помощью клавиатуры, и не работает вообще в Chrome или Safari , Большая проблема с использованием activeElement (кроме IE) заключается в том, что он не обновляется последовательно до тех пор, пока после событие blur не будет обработано, и может вообще не иметь действительного значения во время обработки! Это может быть смягчено путем изменения техники, в которой Михил использовал :

function showBlur(ev)
{
  // Use timeout to delay examination of activeElement until after blur/focus 
  // events have been processed.
  setTimeout(function()
  {
    var target = document.activeElement;
    document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
  }, 1);
}

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

58 голосов
/ 25 октября 2015

2015 ответ : в соответствии с событиями пользовательского интерфейса , вы можете использовать свойство relatedTarget события:

Используется для идентификации вторичного EventTarget, связанного с Фокусом событие, в зависимости от типа события.

Для blur событий,

relatedTarget: цель события получение фокуса.

Пример: * * тысяча тридцать-один

function blurListener(event) {
  event.target.className = 'blurred';
  if(event.relatedTarget)
    event.relatedTarget.className = 'focused';
}
[].forEach.call(document.querySelectorAll('input'), function(el) {
  el.addEventListener('blur', blurListener, false);
});
.blurred { background: orange }
.focused { background: lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become lime.</p>
<input /><input /><input />

Примечание. Firefox не будет поддерживать relatedTarget до версии 48 ( ошибка 962251 , MDN ).

17 голосов
/ 24 сентября 2008

Я решил это в конце концов с помощью таймаута для события onblur (благодаря совету друга, который не является StackOverflow):

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>

Работает как в FF, так и в IE.

16 голосов
/ 03 апреля 2010

Можно использовать событие размытия документа вместо размытия:

$(document).mousedown(function(){
  if ($(event.target).attr("id") == "mySpan") {
    // some process
  }
});
6 голосов
/ 02 декабря 2016

Экземпляры типа FocusEvent имеют атрибут relatedTarget, однако до версии 47 FF, в частности, этот атрибут возвращает ноль, из 48 уже работает.

Вы можете увидеть больше здесь .

2 голосов
/ 07 октября 2008

Я также пытаюсь заставить Autocompleter игнорировать размытие, если щелкнул конкретный элемент и есть рабочее решение, но только для Firefox из-за явногоOriginalTarget

Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
        function(origfunc, ev) {
            if ($(this.options.ignoreBlurEventElement)) {
                var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
                if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
                    return origfunc(ev);
                }
            }
        }
    );

Этот код оборачивает метод onBlur по умолчанию для Autocompleter и проверяет, установлены ли параметры ignoreBlurEventElement. если он установлен, он каждый раз проверяет, является ли нажатый элемент ignoreBlurEventElement или нет. Если это так, Autocompleter не вызывает onBlur, иначе он вызывает onBlur. Единственная проблема с этим заключается в том, что он работает только в Firefox, потому что свойство clearOriginalTarget является специфическим для Mozilla. Теперь я пытаюсь найти другой способ, чем использовать явныйOriginalTarget. Решение, которое вы упомянули, требует, чтобы вы добавили поведение onclick вручную к элементу. Если мне не удастся решить проблему явной цели, я думаю, что последую вашему решению.

2 голосов
/ 24 сентября 2008

Можете ли вы изменить то, что вы проверяете и когда? То есть, если вспомнить, что было размыто последним:

<input id="myInput" onblur="lastBlurred=this;"></input>

и затем в onClick для вашего диапазона вызовите функцию () с обоими объектами:

<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>

Ваша функция может затем решить, следует ли запускать элемент управления Ajax.AutoCompleter. Функция имеет клик-объект и размытый объект. OnBlur уже произошел, поэтому предложения не исчезнут.

1 голос
/ 23 сентября 2008

я думаю, что это невозможно, с IE вы можете попробовать использовать window.event.toElement, но это не работает с Firefox!

1 голос
/ 06 мая 2017
  • document.activeElement может быть родительским узлом (например, узел тела, потому что он находится во временной фазе переключения с цели на другую), поэтому он не может использоваться для вашей области действия
  • ev.explicitOriginalTarget не всегда оценивается

Таким образом, лучший способ - использовать onclick для события body, чтобы косвенно понять, что ваш узел (event.target) размыт

1 голос
/ 13 января 2012

Используйте что-то вроде этого:

var myVar = null;

А потом внутри вашей функции:

myVar = fldID;

А потом:

setTimeout(setFocus,1000)

А потом:

function setFocus(){ document.getElementById(fldID).focus(); }

Финальный код:

<html>
<head>
    <script type="text/javascript">
        function somefunction(){
            var myVar = null;

            myVar = document.getElementById('myInput');

            if(myVar.value=='')
                setTimeout(setFocusOnJobTitle,1000);
            else
                myVar.value='Success';
        }
        function setFocusOnJobTitle(){
            document.getElementById('myInput').focus();
        }
    </script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...