Когда происходит событие «размытия», как я могу узнать, на какой элемент перешел фокус?

StackOverflow https://stackoverflow.com/questions/121499

  •  02-07-2019
  •  | 
  •  

Вопрос

Предположим, я прикрепляю blur в поле ввода HTML следующим образом:

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

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

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

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

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

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

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

Это было полезно?

Решение

Хм...В 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 не устанавливает фокус на кнопках, которые щелкнул (против.вкладка в).

Другие советы

ответ 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, МДН).

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

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

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

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

$(document).mousedown(function(){
  if ($(event.target).attr("id") == "mySpan") {
    // some process
  }
});

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

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

Я также пытаюсь заставить автозаполнение игнорировать размытие, если щелкнул определенный элемент, и имею рабочее решение, но только для 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 или нет.Если это так, автозаполнение не вызывает onBlur, иначе он вызывает onBlur.Единственная проблема заключается в том, что это работает только в Firefox, поскольку свойство явноеOriginalTarget является специфичным для Mozilla.Теперь я пытаюсь найти другой способ, кроме использования явногоOriginalTarget.Упомянутое вами решение требует, чтобы вы вручную добавили поведение onclick к элементу.Если мне не удастся решить явную проблемуOriginalTarget, думаю, я воспользуюсь вашим решением.

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

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

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

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

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

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

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>

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

Как отмечено в этот ответ, вы можете проверить значение document.activeElement. document — это глобальная переменная, поэтому вам не нужно делать никаких магических действий, чтобы использовать ее в обработчике onBlur:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}
  • document.activeElement может быть родительским узлом (например, узлом тела, поскольку он находится во временной фазе переключения с цели на другую), поэтому его нельзя использовать для вашей области действия.
  • ev.explicitOriginalTarget не всегда оценивается

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

Редактировать:Хитрый способ сделать это — создать переменную, которая отслеживает фокус для каждого интересующего вас элемента.Итак, если вас волнует, что «myInput» потерял фокус, установите для него переменную в фокусе.

<script type="text/javascript">
   var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />

Оригинальный ответ:Вы можете передать «это» в функцию.

<input id="myInput" onblur="function(this){
   var theId = this.id; // will be 'myInput'
}" />

Я предлагаю использовать глобальные переменные Blufrom и Blurto.Затем настройте все элементы, которые вам нужны, чтобы назначать их положение в DOM переменной размытия, когда они теряют фокус.Кроме того, настройте их так, чтобы при получении фокуса переменная Blurto устанавливалась на их положение в ДОМ.Затем вы можете использовать другую функцию для анализа данных размытия и размытия.

имейте в виду, что решение с явнымOriginalTarget не работает для переходов с ввода текста на ввод текста.

попробуйте заменить кнопки следующими текстовыми вводами, и вы увидите разницу:

<input id="btn1" onblur="showBlur(event)" value="text1">
<input id="btn2" onblur="showBlur(event)" value="text2">
<input id="btn3" onblur="showBlur(event)" value="text3">

Я экспериментировал с этой же функцией и обнаружил, что FF, IE, Chrome и Opera имеют возможность предоставлять исходный элемент события.Я не тестировал Safari, но предполагаю, что там может быть что-то похожее.

$('#Form').keyup(function (e) {
    var ctrl = null;
    if (e.originalEvent.explicitOriginalTarget) { // FF
        ctrl = e.originalEvent.explicitOriginalTarget;
    }
    else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
        ctrl = e.originalEvent.srcElement;
    }
    //...
});

Мне не нравится использовать тайм-аут при кодировании JavaScript, поэтому я бы сделал это наоборот, как это сделал Михил Боркент.(Код не пробовал, но идея должна быть понятна).

<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>

В голове что-то такое

<head>
    <script type="text/javascript">
        function sortOfCallback(id){
            bluredElement = document.getElementById(blured);
            // Do whatever you want on the blured element with the id of the focus element


        }

    </script>
</head>

Вы можете исправить IE с помощью:

 event.currentTarget.firstChild.ownerDocument.activeElement

Для FF это выглядит как «explicitOriginalTarget».

Антуан и Джей

Я написал альтернативное решение как сделать любой элемент фокусируемым и «размытым».

Он основан на создании элемента как contentEditable и скрыть его визуально и отключить сам режим редактирования:

el.addEventListener("keydown", function(e) {
  e.preventDefault();
  e.stopPropagation();
});

el.addEventListener("blur", cbBlur);
el.contentEditable = true;

ДЕМО

Примечание:Протестировано в Chrome, Firefox и Safari (OS X).Не уверен насчет IE.


Связанный:Я искал решение для VueJ, поэтому тех, кому интересно/интересно, как реализовать такую ​​функциональность с помощью директивы Vue Focusable, пожалуйста. взглянем.

Работает в Google Chrome v66.x, Mozilla v59.x и Microsoft Edge...Решение с помощью jQuery.

Я тестирую в Internet Explorer 9 и не поддерживается.

$("#YourElement").blur(function(e){
     var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
     console.log(InputTarget);
     if(target == "YourId") { // If you want validate or make a action to specfic element
          ... // your code
     }
});

Прокомментируйте свой тест в других версиях Internet Explorer.

Я вижу в ответах только хаки, но на самом деле есть встроенное решение, очень простое в использовании:По сути, вы можете захватить элемент фокуса следующим образом:

const focusedElement = document.activeElement

https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement

Сюда:

<script type="text/javascript">
    function yourFunction(element) {
        alert(element);
    }
</script>
<input id="myinput" onblur="yourFunction(this)">

Или, если вы подключите прослушиватель через JavaScript (в этом примере jQuery):

var input = $('#myinput').blur(function() {
    alert(this);
});

Редактировать:извини.Я неправильно прочитал вопрос.


Я думаю, что это легко возможно с помощью jquery, передав ссылку на поле, вызывающее событие onblur, в «this».
Например,

<input type="text" id="text1" onblur="showMessageOnOnblur(this)">

function showMessageOnOnblur(field){
    alert($(field).attr("id"));
}

Спасибо
Моника

Вы могли бы сделать это так:

<script type="text/javascript">
function myFunction(thisElement) 
{
    document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top