Когда происходит событие «размытия», как я могу узнать, на какой элемент перешел фокус?
-
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)"/>