Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Принцип устройства конвертирования (https://javascript.ru/forum/misc/77931-princip-ustrojjstva-konvertirovaniya.html)

MC-XOBAHCK 03.07.2019 22:12

Принцип устройства конвертирования
 
Здравствуйте!
Покажите пожалуйста схему как делать конвертирование. Я видел что вводят unit с массивами значений (мне laimas как то помог), но я не смог уловить саму идею в контексте большого скрипта. Так как я делаю - это жесть.

Поэтому прошу показать на упрощённом примере решение для таких задач:

1. Измерить удава (из 38 попугаев)
1 удав = 2 слонёнка = 5 мартышек = 38 попугаев.
Макет:
Удавов: <input type="number" name="animal"><br>
Слонёнка: <input type="number" name="animal"><br>
Мартышек: <input type="number" name="animal"><br>
Попугаев: <input type="number" name="animal"><br>

<script>
    let animals = document.querySelectorAll('input[name="animal"]');

    animals.forEach(el => el.addEventListener('input', function () {

    }));
</script>


Ну а второй пример - классика жанра, единицы длины:
1000мм = 100см = 1м
Макет:
мм: <input type="number" name="unit"><br>
см: <input type="number" name="unit"><br>
м: <input type="number" name="unit"><br>
<script>
    let unit = document.querySelectorAll('input[name="unit"]');

    unit.forEach(el => el.addEventListener('input', function () {

    }));
</script>


Я макеты сделал минимальными, возможно нужно атрибуты какие добавить.
Нужно чтобы при вводе значения в других инпутах показывало сколько это будет в их ед. измерения.

Если не сложно, покажите пожалуйста решение.

рони 03.07.2019 22:58

MC-XOBAHCK,
<!DOCTYPE html>

<html>
<head>
    <title>Untitled</title>
    <meta charset="utf-8">
</head>

<body>
мм: <input type="number" name="unit"><br>
см: <input type="number" name="unit"><br>
м: <input type="number" name="unit"><br>
<script>
        let unit = document.querySelectorAll('input[name="unit"]');
        const rang = [1000, 100, 1];
        unit.forEach((el, i)=> (el.value = rang[i], el.addEventListener('input', function () {
        let val = el.value / rang[i];
        unit.forEach((el, k)=>{
            el.value = val * rang[k]
        })
        })));
</script>

</body>
</html>

рони 03.07.2019 23:13

MC-XOBAHCK,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>
Удавов: <input type="number" name="animal"><br>
Слонёнка: <input type="number" name="animal"><br>
Мартышек: <input type="number" name="animal"><br>
Попугаев: <input type="number" name="animal"><br>

<script>
    let unit = document.querySelectorAll('input[name="animal"]');
    const rang = [1, 2, 5, 38];
    unit.forEach((el, i)=> (el.value = rang[i], el.addEventListener('input', function () {
    let val = el.value / rang[i];
    unit.forEach((el, k)=>{
      el.value = (val * rang[k] *100|0)/100
    })
    })));
</script>

</body>
</html>

Malleys 04.07.2019 06:29

Цитата:

Сообщение от MC-XOBAHCK
Поэтому прошу показать на упрощённом примере решение для таких задач:

Общее решение для таких связанных полей...
addEventListener("input", ({ target }) => {
	const relatedInputs = (target.form || document)
		.querySelectorAll(`input[type="number"][name="${event.target.name}"]`);
	const value = Number(target.value);
	const unit = Number(target.getAttribute("value"));
	
	for(const input of relatedInputs) {
		if(input === event.target) continue;
		input.value = value * Number(input.getAttribute("value")) / unit;
	}
});


MC-XOBAHCK, это решение предполагает, что вы укажете в самих полях в атрибуте value пример конвертации.

Если вы будете указывать отдельно в массиве, то вероятно запутаетесь и сделаете ошибку.

Такая конвертация однотипна, один скрипт может обрабатывать всё поля.

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

Вот пример целиком...

<style>
form {
	display: grid;
	grid-template-columns: 1fr 5fr;
	gap: 1em;
	text-align: right;
	margin: 1em;
	padding: 1em;
	max-width: 30em;
}

form > label {
	display: contents;
}
</style>

<script>

addEventListener("input", ({ target }) => {
	const relatedInputs = (target.form || document)
		.querySelectorAll(`input[type="number"][name="${event.target.name}"]`);
	const value = Number(target.value);
	const unit = Number(target.getAttribute("value"));
	
	for(const input of relatedInputs) {
		if(input === event.target) continue;
		input.value = value * Number(input.getAttribute("value")) / unit;
	}
});

</script>

<form>
	<label>мм: <input type="number" name="unit" value="1000"></label>
	<label>см: <input type="number" name="unit" value="100"></label>
	<label>м:  <input type="number" name="unit" value="1"></label>
</form>

<form>
	<label>Удавов:   <input type="number" name="animal" value="1"></label>
	<label>Слонёнка: <input type="number" name="animal" value="2"></label>
	<label>Мартышек: <input type="number" name="animal" value="5"></label>
	<label>Попугаев: <input type="number" name="animal" value="38"></label>
</form>


Можно с формой, а можно без формы. Форма позволяет изолировать друг от друга одноимённые поля.

Удобно ведь таким образом? Указываешь в поле курсы валют, длины, объёмы, площади и всё остальное, что можно конвертировать, и оно работает!

Вы понимаете, как можно добавить ещё один конвертер?

UPD рони, вы всё-таки запутались в массивах и полях (потому что в двух разных местах) и у вас получается, что 1 м равен 10 см!

Также при таком подходе поля сразу заполнены правильным примером, и у пользователя не складывается впечатление, что ему придётся заполнять все эти поля.

Цитата:

Сообщение от рони
const rang = [1, 2, 5, 38];

Но всё-таки, почему оно звенело?

рони 04.07.2019 10:08

Цитата:

Сообщение от Malleys
Но всё-таки, почему оно звенело?

ну вы сами знаите, что ваша логика или это ваш тонкий юмор, мне не доступны.
Цитата:

Сообщение от Malleys
input.value = value * Number(input.getAttribute("value")) / unit;

Number зачем?

MC-XOBAHCK 04.07.2019 10:43

рони, Спасибо! Именно то что я спрашивал.

Malleys, Спасибо!
В ваших скриптах, как обычно, для меня есть что то новое, познавательное и очень полезное. В 10 строчках - для меня сразу 4 новинки. Закинул код в VSCode (привычная подсветка), посмотрел в доках MDN - всё просто и понятно.
Большое спасибо за ваш пример!

рони 04.07.2019 10:44

Цитата:

Сообщение от Malleys
вы всё-таки запутались в массивах

поправил

Malleys 04.07.2019 11:07

Цитата:

Сообщение от рони
ну вы сами знаете, что ваша логика или это ваш тонкий юмор, мне не доступны.

Вы назвали переменную rang, прошедшее время от ring... Типо это прозвоненные значения? Только как-то не складно! Типо колокольчик звенит, когда меняются связанные поля? Но почему оно названо так, как будто ему больше не надо звенеть?

Цитата:

Сообщение от рони
Number зачем?

Приведение типа String к типу Number.

Цитата:

Сообщение от рони
ну вы сами знаете, что ваша логика или это ваш тонкий юмор, мне не доступны.

Или это скрытая реклама индийского кино? Или программный сбой .. .. .... . .. . https://youtu.be/CPlcYKLQg_k

MC-XOBAHCK 04.07.2019 11:18

Цитата:

Сообщение от рони
Number зачем?

Наверное потому что
typeof input.getAttribute("value") == 'string'

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

Для меня вот такой подход с конструктором Number - это приятная новинка, упрощающая жизнь:
const value = Number(target.value);

Признаюсь, я раньше так никогда не делал. Теперь для чисел только так буду парсить значения.

рони 04.07.2019 11:43

Цитата:

Сообщение от MC-XOBAHCK
Наверное потому что

в коде нет сложения, поэтому приведение к Number избыточно.
Цитата:

Сообщение от MC-XOBAHCK
const value = Number(target.value);

как вариант
const value = +target.value;
const value =  target.value * 1;


Часовой пояс GMT +3, время: 18:30.