Я пытаюсь .focus() текстовое поле, когда пользователь нажимает на больший div. Ввод является дочерним элементом div, и я могу найти элемент, однако Javascript выдает ошибку при попытке выполнить функцию .focus().
Я уже пытался напрямую .focus() дочерние узлы, как показано, но я не могу 1) сфокусировать узел и 2) найти входной тег в списке.
function clickables() {
let clickables = document.getElementsByClassName("clickables")
for (var i = 0; i < clickables.length; i++) {
clickables[i].addEventListener("click", function(e) {
const target = e.srcElement.childNodes;
target.focus(input); // .getElementsByTagNames isn't working
});
}
}
clickables();
Ожидаемые результаты заключаются в том, что при нажатии на больший div он сфокусирует ввод внутри него, фактический результат - это java-скрипт, выдающий ошибку.
Пожалуйста, напишите точную ошибку, а также
Было бы очень полезно, если бы вы предоставили нам полный код html и js. В codepen, jsfiddle или около того.
@Vinaayakh TypeError: e.srcElement.childNodes.getElementsByTagName не является функцией
Вероятно, вам следует избегать давать переменной то же имя, что и функция, в которой она находится.
Во-первых, вы должны использовать inputs.length
, а не clickables.length
.
Во-вторых, вам нужно выбрать, какой ребенок .focus()
.
function clickables() {
let inputs = document.getElementsByClassName("clickables");
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("click", function(e) {
const target = e.srcElement.firstElementChild;
target.focus();
});
}
}
clickables();
.clickables {
background-color: #999;
padding: 10px;
}
<div class = "clickables">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third">
</div>
В этом примере я выбираю первый элемент, на котором нужно сосредоточиться.
ОБНОВИТЬ
Как уже говорилось, вам нужно знать ребенка который, которому вы хотите вызвать .focus()
.
Допустим, вы используете атрибут autofocus
для ребенка, которому хотите получить фокус, тогда вы можете сделать это:
function clickables() {
let inputs = document.getElementsByClassName("clickables");
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("click", function(e) {
let target = e.srcElement.querySelector('[autofocus]');
if (!target) {
target = e.srcElement.firstElementChild;
}
target.focus();
});
}
}
clickables();
.clickables {
background-color: #999;
padding: 10px;
}
<div class = "clickables">
<input type = "text" value = "first">
<input type = "text" value = "second" autofocus>
<input type = "text" value = "third">
</div>
<hr>
<div class = "clickables">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third" autofocus>
</div>
<hr>
<div class = "clickables">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third">
</div>
Поскольку @sean правильно указал, что в приведенном выше примере отсутствует использование autofocus
, вам, вероятно, следует использовать другой атрибут или вот альтернативный способ выполнить то же самое:
function clickables() {
let inputs = document.getElementsByClassName("clickables");
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("click", function(e) {
let index = Number(e.srcElement.getAttribute('focus')||'1')-1;
console.info(index)
let target = e.srcElement.children[index];
target.focus();
});
}
}
clickables();
.clickables {
background-color: #999;
padding: 10px;
}
<div class = "clickables" focus = "2">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third">
</div>
<hr>
<div class = "clickables" focus = "3">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third">
</div>
<hr>
<div class = "clickables">
<input type = "text" value = "first">
<input type = "text" value = "second">
<input type = "text" value = "third">
</div>
I think the attribute is the best solution since you can guarantee setting
.focus
on the correct/expected element.
Это здорово, за исключением того, что у меня есть несколько дочерних элементов, и порядок определен, а .getElementsByTagName выдает ошибку, есть ли способ фильтровать специально вводимые теги?
Это неправильное использование атрибута autofocus
, который указывает браузерам автоматически фокусировать ввод на загрузке страницы. Вместо этого предложите использовать собственный атрибут data-*
или класс.
Это может быть, но вы можете использовать ЛЮБОЙ атрибут для этого. Это всего лишь один из способов сообщить коду, на каком поле ввода следует сосредоточиться при нажатии на <div>
. Хорошая особенность использования autofocus
заключается в том, что первый <div>
будет сфокусирован на правильном элементе.
Да, вы можете использовать любой атрибут для этого. Но использование autocomplete
автоматически сфокусирует первое <input>
на загрузке страницы. Это может создать проблемы с доступностью, и автор вопроса не сказал, что они хотят, чтобы ввод автоматически фокусировался на загрузке страницы. Лучше использовать другой атрибут, чем создавать нежелательное поведение.
Вы можете попробовать что-то вроде
function clickables() {
let inputs = document.getElementsByClassName("clickables")
for (var i = 0; i < clickables.length; i++) {
clickables[i].addEventListener("click", function(e) {
const childElements = e.srcElement.children;
for (var j = 0; j < childElements.length; j++) {
childElements[j].focus();
}
});
}
}
clickables();
Это не сработает, так как вы получаете список элементов в переменной inputs
, а затем пытаетесь выполнить итерацию по clickables
, которая является функцией.
Разве дочерние узлы не возвращают массив? Так что, может быть, вам нужно пройтись по узлу?