@Reflections

Как связать кнопку с соответствующим объектом?

Доброй ночи всем. Подскажите пожалуйста.

Есть n-ое кол-во кнопок. Их может быть сколько угодно. Каждая кнопка - это определенный тип значения.
<div class="values">
				<div class="mass value-item basic__btn value-active basic__shadow">
					<p class="value-item__title">Масса</p>
					<img src="assets/img/values/mass.svg" alt="" class="svg-icon value-item__img">
				</div>
				<div class="distance value-item basic__btn">
					<p class="value-item__title">Расстояние</p>
					<img src="assets/img/values/distance.svg" alt="" class="svg-icon value-item__img">
				</div>
				<div class="temperature value-item basic__btn">
					<p class="value-item__title">Температура</p>
					<img src="assets/img/values/temperature.svg" alt="" class="svg-icon value-item__img">
				</div>
				<div class="time value-item basic__btn">
					<p class="value-item__title">Время</p>
					<img src="assets/img/values/time.svg" alt="" class="svg-icon value-item__img">
				</div>
				<div class="speed value-item basic__btn">
					<p class="value-item__title">Скорость</p>
					<img src="assets/img/values/speed.svg" alt="" class="svg-icon value-item__img">
				</div>
				<div class="currency value-item basic__btn">
					<p class="value-item__title">Валюта</p>
					<img src="assets/img/values/currency.svg" alt="" class="svg-icon value-item__img">
				</div>
			</div>


Есть отдельный js-файл вот с такой структурой (остальные объекты, помимо mass точно такие же по структуре):
let mass = {
	ton: {
		name: "Тонна",
		value: 1000
		},
	centner: {
		name: "Центнер",
		value: 100
		},
	kg: {
		name: "Килограмм",
		value: 1
		},
	g: {
		name: "Грамм",
		value: 0.001
		},
	mg: {
		name: "Миллиграмм",
		value: 0.000001
		},
	carat: {
		name: "Карат",
		value: 20
		}
};


И есть массив, этих объектов:
let valueTypes = [mass, distance, temperature, time, speed, currency];


Список значений каждого объекта подгружается в ul-список.
<div class="converter-box">
						<ul class="converter-box__list">
							<li class="converter-box__list-item current-value">Килограмм</li>
							<ul class="dropdown-list hidden">
								<!--Список подгружается из объекта values.js-->
							</ul>
						</ul>
						<div class="converter-box__input-block">
							<input type="tel" value="1" class="converter-box__input">
						</div>
					</div>


Предполагается, что при клике на каждую кнопку должны подгружаться имена всех нужных объектов (в случае с mass, это mass.kg.name, mass.g.name и.т.д.). У меня получилось сделать это "тупым" способом, просто скопировав код для каждой кнопки.

let elements = document.querySelectorAll(".value-item");
let massBtn = elements[0],
	 distanceBtn = elements[1],
	 temperatureBtn = elements[2],
	 timeBtn = elements[3],
	 speedBtn = elements[4],
	 currencyBtn = elements[5];

//mass
massBtn.addEventListener('click', function() {
	while (valuesListItems.length != 0) {
		i = 0;
		valuesListItems[i].remove();
		i++;
	}

	for (key in mass) {
		let massValue = mass[key];
		massValueName = massValue.name
		for (let i = 0; i < valuesList.length; i++) {
			valuesList[i].insertAdjacentHTML('afterbegin', (`<li class="converter-box__list-item dropdown-list__item">${massValueName}</li>`));
		}
	};
	valuesListCurrent[0].innerHTML = mass.kg.name;
	valuesListCurrent[1].innerHTML = mass.g.name;

	for (let i = 0; i < valuesList.length; i++) {
		const currentValue = valueToConvert[i];
		const currentList = valuesList[i];
		const currentListItems = currentList.children;
	
		currentValue.addEventListener('mouseenter', function() {
			currentList.classList.remove('hidden');
		});
	
		currentValue.addEventListener('mouseleave', function() {
			currentList.classList.add('hidden');
		});
		
		currentList.addEventListener('mouseenter', function() {
			currentList.classList.remove('hidden');
		});
	
		currentList.addEventListener('mouseleave', function() {
			currentList.classList.add('hidden');
		});
	
		for (let j = 0; j < currentListItems.length; j++) {
			const currentItem = currentListItems[j]
	
			currentItem.addEventListener('click', (e) => {
				let text = currentItem.textContent
				currentValue.textContent = text
				currentList.classList.add('hidden');
			});
		};
	};
});


И вот так для каждой кнопки. Понимаю, что это максимально негибкий код, понимаю, что можно сделать единым движением обработку для всех кнопок, пусть их даже будет 30, но по факту не могу сообразить, как привязать соответствующий объект каждой кнопке. Как провести сравнение (если необходимо).

Буду благодарен за помощь.
  • Вопрос задан
  • 223 просмотра
Решения вопроса 1
sergiks
@sergiks Куратор тега JavaScript
♬♬
можно, например, кнопки не писать в разметке, а создавать программно. Для кнопки нужны только название и имя картинки, а в остальном они одинаковы. Ну ещё активная кнопка получает 2 доп. CSS класса.

Для отрисовки достаточно объекта типа
spoiler
const categories = {
  mass: 'Масса',
  distance: 'Расстояние',
  temperature: 'Температура',
  time: 'Время',
  speed: 'Скорость',
  currency: 'Валюта',
};


Там же, где создаются кнопки и вешается на них слушатель клика, можно их складывать в массив. И вот у вас массив элементов. Ещё каждой категории понадобятся данные с единицами измерения. Поэтому центральный объект данных можно примерно так представить:
spoiler
const categories = {
  mass: { title: 'Масса', element: null, data: null, },
  distance: { title: 'Расстояние', element: null, data: null, },
  temperature: { title: 'Температура', element: null, data: null, },
  time: { title: 'Время', element: null, data: null, },
  speed: { title: 'Скорость', element: null, data: null, },
  currency: { title: 'Валюта', element: null, data: null, },
};
В поле element пойдёт созданный HTML-элемент кнопки, а в поле data – что там сейчас в переменной mass у вас.

Клик по объекту вешать сразу с этим же текущим объектом всех-данных:
Object.entries(categories).forEach(([ name, item ]) => {
  const el = document.createElement('div'); // это внешний div кнопки
  // el.classList.add(...)
  el.insertAdjacentHTML('beforeend', `
    <p class="value-item__title">${item.title}</p>
      <img src="assets/img/values/${name}.svg" alt="" class="svg-icon value-item__img">
  `);
  el.addEventListener('click', () => clickHandler(name));
  // по этому name можно вытащить categories[name]

  divValues.appendChild(el);
});
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы