Когда происходит событие "размытия", как я могу узнать, какой элемент focus пошел *в*?
предположим, я приложу blur функция в поле ввода HTML, как это:
<input id="myInput" onblur="function() { ... }"></input>
есть ли способ получить идентификатор элемента, который вызвал blur событие для запуска (элемент, который был нажат) внутри функции? Как?
например, предположим, что у меня период такой:
<span id="mySpan">Hello World</span>
если я нажму на промежуток сразу после того, как входной элемент будет иметь фокус, входной элемент потеряет фокус. Как функция знает, что это было mySpan что было щелкнул?
PS: Если событие onclick диапазона произойдет до события onblur входного элемента, моя проблема будет решена, потому что я могу установить некоторое значение состояния, указывающее, что определенный элемент был нажат.
PPS: предыстория этой проблемы заключается в том, что я хочу вызвать внешний элемент управления AJAX autocompleter (из кликабельного элемента), чтобы показать свои предложения, без того, чтобы предложения немедленно исчезли из-за blur событие на входе элемент. Поэтому я хочу проверить в blur функция, если был нажат один конкретный элемент, и если это так, игнорировать событие размытия.
23 ответов:
Мда... В 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) заключается в том, что он не постоянно обновляется до после theblurсобытие было обработано, и может не иметь действительного значения вообще во время обработки! Это может быть смягчено с изменением на техника Michiel в конечном итоге с помощью: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,MDN).
Я решил это в конечном итоге с таймаутом на onblur событие (благодаря совету друга, который не StackOverflow):
<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input> <span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>работает как в FF, так и в IE.
можно использовать mousedown событие документа вместо размытия:
$(document).mousedown(function(){ if ($(event.target).attr("id") == "mySpan") { // some process } });
тип
FocusEventэкземпляровrelatedTargetатрибут, однако, до версии 47 FF, в частности, этот атрибут возвращает null, из 48 уже работает.Вы можете видеть больше здесь.
Я также пытаюсь заставить Autocompleter игнорировать размытие, если конкретный элемент нажат и имеет рабочее решение, но только для Firefox из-за explicitOriginalTarget
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, потому что свойство explicitOriginalTarget является специфичным для Mozilla . Теперь я пытаюсь найти другой способ, чем с помощью explicitOriginalTarget. Решение, которое вы упомянули, требует, чтобы вы добавили поведение onclick вручную к элементу. Если мне не удастся решить проблему explicitOriginalTarget, я думаю, я буду следовать вашему решению.
можете ли вы отменить то, что вы проверяете и когда? То есть, если вы помните, что было размыто в последний раз:
<input id="myInput" onblur="lastBlurred=this;"></input>а затем в onClick для вашего span, вызовите функцию () с обоими объектами:
<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>
Я думаю, что это не возможно, с IE вы можете попробовать использовать
window.event.toElement, но он не работает с Firefox!
как отметил в ответ, вы можете проверить значение
document.activeElement.document- это глобальная переменная, поэтому вам не нужно делать никакой магии, чтобы использовать ее в своем обработчике onBlur:function myOnBlur(e) { if(document.activeElement === document.getElementById('elementToCheckForFocus')) { // Focus went where we expected! // ... } }
- документ.activeElement может быть родительским узлом (например, body node, поскольку он находится во временном фазовом переключении с целевого объекта на другой), поэтому он не может использоваться для вашей области
- ev.explicitOriginalTarget не всегда ценится
поэтому лучший способ-использовать onclick on body event для косвенного понимания вашего узла (event.target) находится на размытии
Edit: Хакерский способ сделать это-создать переменную, которая отслеживает фокус для каждого элемента, о котором вы заботитесь. Итак, если вам не все равно, что "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' }" />
Я предлагаю использовать глобальные переменные blurfrom и blurto. Затем настройте все элементы, о которых вы заботитесь, чтобы назначить их положение в DOM переменной blurfrom, когда они теряют фокус. Кроме того, настройте их так, чтобы получение фокуса установило переменную blurto в их положение в DOM. Затем вы можете использовать другую функцию для анализа данных blurfrom и blurto.
имейте в виду, что решение с explicitOriginalTarget не работает для перехода от ввода текста к вводу текста.
попробуйте заменить кнопки со следующими текстовыми вводами, и вы увидите разницу:
<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, поэтому я бы сделал это противоположным способом Michiel Borkent. (Не пробовал код позади, но вы должны получить идею).
<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это выглядит как" explicitOriginalTarget " для FF.
Антуан И J
Я написал альтернативный вариант как сделать любой элемент фокусируемым и"blurable".
Он основан на создании элемента как
contentEditableи скрытие визуально его и отключение самого режима редактирования:el.addEventListener("keydown", function(e) { e.preventDefault(); e.stopPropagation(); }); el.addEventListener("blur", cbBlur); el.contentEditable = true;Примечание: протестировано в Chrome, Firefox и Safari (OS X). Не уверен насчет IE.
связанный: я искал решение для VueJs, поэтому для тех, кто заинтересован / любопытно, как реализовать такие функциональность с помощью директивы 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.activeElementhttps://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); });Edit: к сожалению. Я неправильно понял вопрос.
Я думаю, что это легко возможно через 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)"/>
Comments