Добрый день. <br/> <br/> У меня есть следующий код: <br/> <br/> <pre><code class="javascript">function box(nameBlock, options, callback) {
var code = options.code ? options.code : [];
var inputs = [];
var currentBlock = document.querySelector('#' + nameBlock);
for (var i = 0; i < code.length; i++)
if (code[i] == nameBlock) {
currentBlock.innerHTML = callback();
for (var j = 0; j < currentBlock.querySelectorAll('input').length; j++) inputs.push(currentBlock.querySelectorAll('input')[j].getAttribute('name'));
callback(null, null, inputs);
}
}</code></pre> <br/> <br/> А вот как он используется: <br/> <br/> <pre><code class="javascript">box('test', {}, function(error, result, page){
return '<div>Auth</div><br><input name="login" placeholder="Enter login"><br><input name="password" placeholder="Enter password">';
});</code></pre> <br/> <br/> Основная задача — отправить HTML-код через return обратно в функцию, чтобы он корректно отображался на странице. Однако, у меня есть необходимость передать информацию об inputs из блока в переменную page и использовать их результаты в разметке до отправки в return. Проблема в том, что доступ к inputs возможен только после вставки кода из return, так как в этот момент они еще не добавлены в разметку. В результате, при попытке получить доступ к inputs сначала возвращается undefined, а затем уже получаются данные inputs, которые нельзя использовать. <br/> <br/> Вопрос — возможно ли как-то извлечь разметку из...
Да, вы можете решить эту задачу, изменив подход к обработке HTML-кода и получения данных из элементов формы. Вместо того чтобы пытаться получить данные о полях ввода сразу после вставки кода, вы можете сначала создать временный элемент, в который будет помещен ваш HTML, а затем извлекать из него необходимые значения. Это позволит вам избежать проблемы с попыткой доступа к элементам, которые еще не добавлены в документ.
Вот обновленный код на основе вашего, который решает вашу проблему:
```javascript
function box(nameBlock, options, callback) {
var code = options.code ? options.code : [];
var currentBlock = document.querySelector('#' + nameBlock);
for (var i = 0; i < code.length; i++) {
if (code[i] == nameBlock) {
// Получаем HTML-код из callback
var html = callback();
// Создаем временный элемент для парсинга HTML
var tempDiv = document.createElement('div');
tempDiv.innerHTML = html;
// Вставляем HTML-код в текущий блок
currentBlock.innerHTML = tempDiv.innerHTML;
// Теперь получаем все input-поля
var inputs = [];
var inputElements = currentBlock.querySelectorAll('input');
for (var j = 0; j < inputElements.length; j++) {
inputs.push(inputElements[j].getAttribute('name'));
}
// Передаем полученные данные в callback
callback(null, null, inputs);
}
}
}
// Пример использования
box('test', {}, function(error, result, page) {
return '<div>Auth</div><br><input name="login" placeholder="Enter login"><br><input name="password" placeholder="Enter password">';
});
```
### Что изменилось:
1. **Создание временного элемента:** Мы создаем элемент `div`, чтобы временно хранить HTML-код, который возвращает ваш callback. Это позволяет безопасно работать с ним без необходимости напрямую вставлять его в документ сразу.
2. **Извлечение input-полей:** После вставки HTML-кода из временного элемента в `currentBlock`, мы можем безопасно извлекать имена input-полей, так как они уже были добавлены в разметку.
Таким образом, вы получаете возможность сначала подготовить HTML и потом извлечь информацию о полях ввода, а полученные данные можно передать обратно в callback или использовать по вашему усмотрению.
Вот в таких ситуациях я понимаю, зачем придумали VueJS )).
А если решить задачу в рамках существующего стека, то где-то тут нужно прервать поток выполнения JS функцией setTimeout с нулевым временем ожидания, и продолжить работать с инпутами внутри вызываемой функции setTimeout. Это позволит передать управление браузеру, чтобы он успел отрисовать то, что закинуто в DOM через innerHTML:
if (code[i] == nameBlock) { currentBlock.innerHTML = callback(); setTimeout(function(currentBlock, inputs) { for (var j = 0; j < currentBlock.querySelectorAll('input').length; j++) inputs.push(currentBlock.querySelectorAll('input')[j].getAttribute('name')); callback(null, null, inputs); }, 0, // нулевое время setTimeout currentBlock, inputs // проверьте, чтобы правильно передавались аргументы внутрь setTimeout ); break; // тут, наверное, можно прерывать внешний цикл, раз нашли нужное }