Как упростить этот код javascript
в жс я нолик ) Передо мной встала написать код, я сделал, оно работает, но хотелось бы узнать как можно упростить эту громадину
document.addEventListener('DOMContentLoaded', function () {
const form1 = document.getElementById('form1');
const form2 = document.getElementById('form2');
const form3 = document.getElementById('form3');
const form4 = document.getElementById('form4');
const btnS1 = document.getElementById('btnS1');
const btnS2 = document.getElementById('btnS2');
const btnS3 = document.getElementById('btnS3');
const btnS4 = document.getElementById('btnS4');
btnS1.addEventListener("click", function() {
form1.classList.add('active');
form2.classList.remove('active');
form3.classList.remove('active');
form4.classList.remove('active');
});
btnS2.addEventListener("click", function() {
form2.classList.add('active');
form1.classList.remove('active');
form3.classList.remove('active');
form4.classList.remove('active');
});
btnS3.addEventListener("click", function() {
form3.classList.add('active');
form1.classList.remove('active');
form2.classList.remove('active');
form4.classList.remove('active');
});
btnS4.addEventListener("click", function() {
form4.classList.add('active');
form1.classList.remove('active');
form2.classList.remove('active');
form3.classList.remove('active');
});
});
Ответы (4 шт):
Можно всем кнопкам задать 1 класс, вместо того чтобы каждый раз обращаться по id кнопки. И по атрибуту data-target у кнопки менять активный класс формы.
const callToActionBtns = document.querySelectorAll(".btn");
callToActionBtns.forEach((btn) => {
btn.addEventListener("click", (e) => {
callToActionBtns.forEach(b => {
form = document.querySelector(b.getAttribute('data-target'));
form.classList.remove('active');
});
form = document.querySelector(e.target.getAttribute('data-target'));
form.classList.toggle("active");
});
});
.forms {
display: none;
}
.active {
display: block;
border: 3px solid #eee;
padding-bottom: 1rem;
margin-bottom: 1rem;
}
<div>
<div id="form1" class="forms active">1</div>
<div id="form2" class="forms">2</div>
<div id="form3" class="forms">3</div>
<button data-target="#form1" class="btn">1</button>
<button data-target="#form2" class="btn">2</button>
<button data-target="#form3" class="btn">3</button>
</div>
Если я правильно понял как должна выглядеть разметка, то проще всего было использовать механику табов (вкладок).
Написал механику под неё, теперь можно кнопок и "форм" создавать хоть миллион
document.addEventListener('DOMContentLoaded', function() {
let btns = document.querySelector('.btns'),
forms = document.querySelector('.forms');
btns.addEventListener('click', function(e) {
let target = e.target.closest('.btn');
if(target) {
let id = target.getAttribute('data-form');
if(!target.classList.contains('active')) {
let old = btns.querySelector('.btn.active');
if(old) old.classList.remove('active');
target.classList.add('active');
let form = forms.querySelector('#'+id);
if(form) {
old = forms.querySelector('.form.active');
if(old) old.classList.remove('active');
form.classList.add('active');
}
}
}
});
});
.btns .btn {
display: inline-block;
user-select: none;
cursor: pointer;
}
.btns .btn:not(:last-child) {
margin-right: 10px;
}
.btns .btn.active {
color: green;
}
.forms .form {
display: none;
}
.forms .form.active {
display: block;
}
<div class="btns">
<div class="btn" data-form="form-1">form 1</div>
<div class="btn" data-form="form-2">form 2</div>
<div class="btn" data-form="form-3">form 3</div>
<div class="btn" data-form="form-4">form 4</div>
</div>
<div class="forms">
<div id="form-1" class="form">form 1</div>
<div id="form-2" class="form">form 2</div>
<div id="form-3" class="form">form 3</div>
<div id="form-4" class="form">form 4</div>
</div>
Оставлю этот вариант, на случай, если вам не подойдет делегирование событий как в ответе De.Minov (т.е. кнопки и формы не находятся в одном большом блоке):
const btnToFormsMap = new Map([
['btnS1', 'form1'],
['btnS2', 'form2'],
['btnS3', 'form3'],
['btnS4', 'form4'],
].map(item => [
document.getElementById(item[0]),
document.getElementById(item[1])
]));
let activedForm = null;
document.querySelectorAll('[id^=btnS]').forEach(btn => btn.addEventListener('click', (e) => {
const activeForm = btnToFormsMap.get(e.target);
if (activedForm !== null) activedForm.classList.remove('active');
activeForm.classList.add('active');
activedForm = activeForm;
}));
[id^=btnS] {
cursor: pointer;
}
[id^=form].active {
color: red;
}
<div id="btnS1">btnS 1</div>
<div id="btnS2">btnS 2</div>
<div id="btnS3">btnS 3</div>
<div id="btnS4">btnS 4</div>
<br/>
<div id="form1">form 1</div>
<div id="form2">form 2</div>
<div id="form3">form 3</div>
<div id="form4">form 4</div>
На самом деле можно и тут воспользоваться делегированием, навесив слушатель на весь документ, но подумал, что у вас скорее всего всё статично
Плюсы:
- Для поиска уже активного элемента и будущего активного элемента не надо ничего искать ни в DOM-е ни в массиве
- Очень легко построить нужные связи между кнопками и формами
Минусы:
- Это это не будет работать, если формы и кнопки у вас добавляются динамически, тогда вам необходим ответ
De.Minov
Минус это или плюс, каждый решает для себя, но потребляет больший объём памяти для ускорения алгоритма
Для примера. Вот как это будет выглядеть в jQuery
window.onload = () => {
$("form").each(function () {
var $thisForm = $(this);
$thisForm.click(function () {
$('form').removeClass("active");
$thisForm.addClass("active");
});
});
}
.active {
background: green !important;
}
form {
background: red;
color: #fff;
padding: 10px;
margin: 10px;
}
<form class="form1" action="">Form 1</form>
<form class="form2" action="">Form 2</form>
<form class="form3" action="">Form 3</form>
<form class="form4" action="">Form 4</form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>