JS:
document.getElementsByTagName("input, select, textarea, option, optgroup, fieldset, label").onchange = function () {
var updateRate = document.querySelector('.updateRate');
updateRate.style.display = "block";
};
разметка и стили:
<div class = "updateRate">Update Rate</div>
<style>
.updateRate {
display:none;
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate, .updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}
</style>
Вышесказанное - моя попытка; но баннер по-прежнему не отображается после любого изменения состояния элементов формы.
Обновлять: Итак, оба ответа SO ниже кажутся правильными; но, возможно, я недостаточно объяснил контекст - теперь «баннер» отображается, как только форма начинает заполняться в первый раз; Цель заключалась в том, чтобы баннер отображался после того, как пользователь вернулся и обновил элемент формы (второй раз или изменив его с исходного).
Контекст:Это встроенный инструмент цитат; цитата будет сгенерирована встроенной после заполнения элементов формы. Я пытался создать «баннер», который будет стоять в очереди, если пользователь изменит какой-либо элемент веб-формы во второй раз. Извините за путаницу.
user has gone back - опишите это поподробнее. Откуда? Другая страница? Другая вкладка? Изменить после отправки формы?
Это встроенный инструмент цитат; цитата будет сгенерирована встроенной после заполнения элементов формы. Я пытался создать «кнопку обновления», которая будет стоять в очереди, если пользователь изменит какой-либо элемент веб-формы во второй раз. Извините за путаницу. Мой первоначальный подход был таким: stackoverflow.com/questions/53011986/…



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


.getElementsByTagName() возвращает список узлов (объект, подобный массиву), а не отдельный элемент. Таким образом, у него нет свойства onchange, с которым можно было бы работать. После получения списка узлов вам нужно будет перебрать все элементы в списке и настроить обработчик событий для каждого по одному.
Кроме того, .getElementsByTagName() позволяет передавать только одно имя тега, а не список, разделенный запятыми. Кроме того, он возвращает «список активных узлов», который влияет на производительность, поэтому, если вы не добавляете / удаляете элементы динамически, вам следует избегать этого и вместо этого использовать .querySelectorAll().
Теперь элементы option, optgroup и label могут быть изменены только с помощью кода, и они не генерируют и не получают событие change в первую очередь, поэтому вы на самом деле не хотите / не нуждаетесь в тех, которые включены в ваш список узлов.
Дополнительные комментарии о том, как сделать ваш код более современным и организованным, приведены ниже:
// Get this reference just once and cache it in a variable
var updateRate = document.querySelector('.updateRate');
// Gather up all the relevant elements into a node list
let elements = document.querySelectorAll("input, select, textarea, fieldset");
// Convert the node list into an Array so that .forEach()
// can safely be used to loop in all modern browsers
Array.prototype.slice.call(elements).forEach(function(element){
// Add event listeners the modern way, not with .onXyz properties
element.addEventListener("change", function () {
// Just remove the hidden class already applied to the element
// instead of working with inline styles
updateRate.classList.remove("hidden");
});
});/*
This is applied to the "Update Rate" element in HTML by default.
It can be removed by the JavaScript when appropriate.
*/
.hidden { display:none; }
.updateRate {
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate, .updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}<form>
<fieldset>
<legend>This is the legend</legend>
<input>
<select>
<option>choice 1</option>
<option>choice 2</option>
<option>choice 3</option>
</select>
</fieldset>
<textarea></textarea>
</form>
<!-- Set this element to be hidden by default -->
<div class = "updateRate" class = "hidden">Update Rate</div>Вы не можете присоединить событие таким образом, так как метод getElementsByTagName принимает одно имя тега вы можете использовать метод querySelectorAll() вместо этого, чтобы получить элементы, затем перебрать их, используя foreach, и прикрепить событие, используя addEventListener():
var fields = document.querySelectorAll("input, select, textarea, option, optgroup, fieldset, label");
[].forEach.call(fields, function(el) {
el.addEventListener('change', showUpdateRate, false);
});
function showUpdateRate() {
if (document.querySelector('.quote').textContent != "") {
document.querySelector('.updateRate').style.display = "block";
}
}
document.querySelector('.generate').addEventListener('click', function() {
var quote = document.querySelector('[name = "type"]:checked').value;
document.querySelector('.quote').textContent = quote + " Quote";
});.updateRate {
display: none;
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate,
.updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}<div class = "updateRate">Update Rate</div>
<br><br><br>
<form>
<input type = "radio" name = "type" value = "Success">Success
<input type = "radio" name = "type" value = "Motivation">Motivation
<input type = "radio" name = "type" value = "Work">Work
<br><br>
<input type = "button" class = "generate" value = "Generate">
</form>
<br>
<span class = "quote"></span>Не могли бы вы подробнее описать, что вы имеете в виду под своим обновлением?
Не все браузеры поддерживают вызов .forEach() в списке узлов. Рекомендуется сначала формально преобразовать его в массив.
Проверьте мой обновленный сниппет @ No-Spex ... Он покажет "баннер", только если цитата уже сгенерирована и пользователь изменяет ввод ...
Добавьте соответствующий HTML-код.