Как .focus() a .srcElement/childNode в Javascript

Я пытаюсь .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-скрипт, выдающий ошибку.

Разве дочерние узлы не возвращают массив? Так что, может быть, вам нужно пройтись по узлу?

Vinaayakh 09.04.2019 18:28

Пожалуйста, напишите точную ошибку, а также

Aman B 09.04.2019 18:29

Было бы очень полезно, если бы вы предоставили нам полный код html и js. В codepen, jsfiddle или около того.

AngelMdez 09.04.2019 18:44

@Vinaayakh TypeError: e.srcElement.childNodes.getElementsByTagName не является функцией

karlramirez 09.04.2019 18:45

Вероятно, вам следует избегать давать переменной то же имя, что и функция, в которой она находится.

Intervalia 09.04.2019 19:00
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
857
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Во-первых, вы должны использовать 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 выдает ошибку, есть ли способ фильтровать специально вводимые теги?

karlramirez 09.04.2019 18:53

Это неправильное использование атрибута autofocus, который указывает браузерам автоматически фокусировать ввод на загрузке страницы. Вместо этого предложите использовать собственный атрибут data-* или класс.

Sean 09.04.2019 19:04

Это может быть, но вы можете использовать ЛЮБОЙ атрибут для этого. Это всего лишь один из способов сообщить коду, на каком поле ввода следует сосредоточиться при нажатии на <div>. Хорошая особенность использования autofocus заключается в том, что первый <div> будет сфокусирован на правильном элементе.

Intervalia 09.04.2019 19:08

Да, вы можете использовать любой атрибут для этого. Но использование autocomplete автоматически сфокусирует первое <input> на загрузке страницы. Это может создать проблемы с доступностью, и автор вопроса не сказал, что они хотят, чтобы ввод автоматически фокусировался на загрузке страницы. Лучше использовать другой атрибут, чем создавать нежелательное поведение.

Sean 09.04.2019 19:13

Вы можете попробовать что-то вроде

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, которая является функцией.

Intervalia 09.04.2019 18:54

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