Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Тернарный оператор при выводе API данных (https://javascript.ru/forum/dom-window/78722-ternarnyjj-operator-pri-vyvode-api-dannykh.html)

DVV 25.10.2019 21:46

Тернарный оператор при выводе API данных
 
Сайт получает данные крипто рынка через API. Нужно сделать так, что изменение курса в % (число) в ячейке таблицы было зеленого цвета, если он положительный и красный, если отрицательный


Также надо заменить на прочерк (-) данные, если они отсутствуют (равны Null).

По идее тут надо через тернарный оператор, но не могу понять, куда и как его прописывать.
Еще есть вопрос, почему подчеркивается красным вот такая запись. Ему не нравится, что получаемый через API параметр начинается с числа


рони 25.10.2019 21:59

DVV,
код можно а не картинку, где строка 12?

DVV 25.10.2019 22:05

(function() {

    function exchangeDataShow() {
        fetch('https://api.coinmarketcap.com/v1/ticker/?limit=20')
        .then( (responce) => {
            return responce.json();
        })
        .then( (data) => {
            let output = ' ';
            
            data.forEach(coin => {

                output += `
                    <tr>
                        <td>${coin.rank}</td>
                        <td>${coin.name}</td>
                        <td>${coin.price_usd}</td>
                        <td>${coin.24h_volume_usd}</td>
                        <td>${coin.market_cap_usd}</td>
                        <td>${coin.total_supply}</td>
                        <td>${coin.max_supply}</td>
                        <td>${coin.percent_change_1h}%</td>
                        <td>${coin.percent_change_24h}%</td>
                        <td>${coin.percent_change_7d}%</td>
                    </tr>
                `; 
            });

            document.getElementById('market-data').innerHTML = output;
            
        })
        .catch( (err) => {
            console.log(err);
        });
    }

    window.onload = exchangeDataShow();

    setInterval(() => {
        console.log('reload');
        exchangeDataShow();
    }, 5000);

})();

laimas 25.10.2019 22:10

${coin['24h_volume_usd']}

А для цвета условие меньше нуля то иначе ...

рони 25.10.2019 22:10

DVV,
css сами пропишите.
(function() {

    function exchangeDataShow() {
        fetch('https://api.coinmarketcap.com/v1/ticker/?limit=20')
        .then( (responce) => {
            return responce.json();
        })
        .then( (data) => {
            let output = ' ';

            data.forEach(coin => {
                let cls = coin.percent_change_1h < 0 ? 'red' : 'green';
                output += `
                    <tr>
                        <td>${coin.rank}</td>
                        <td>${coin.name}</td>
                        <td>${coin.price_usd}</td>
                        <td>${coin['24h_volume_usd']}</td>
                        <td>${coin.market_cap_usd}</td>
                        <td>${coin.total_supply}</td>
                        <td>${coin.max_supply}</td>
                        <td class="${cls}">${coin.percent_change_1h}%</td>
                        <td>${coin.percent_change_24h}%</td>
                        <td>${coin.percent_change_7d}%</td>
                    </tr>
                `;
            });

            document.getElementById('market-data').innerHTML = output;

        })
        .catch( (err) => {
            console.log(err);
        });
    }

    window.onload = exchangeDataShow();

    setInterval(() => {
        console.log('reload');
        exchangeDataShow();
    }, 5000);

})();

DVV 25.10.2019 22:15

Спасибо большое. Заработало))

laimas 25.10.2019 22:16

рони,
исправить надо, coin.24h_volume_usd - это ошибка.

DVV 25.10.2019 22:16

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

рони 25.10.2019 22:18

laimas,
добавил

laimas 25.10.2019 22:22

Цитата:

Сообщение от DVV
не дошло, куда именно

Да можно было прямо в тег и без тернарного оператора, ведь какой-то из этих цветов ячейка все равно будет иметь. :)

DVV 25.10.2019 22:25

а как? и как заменить null на пробел, если данных нет

рони 25.10.2019 22:27

DVV,
${....||""}

рони 25.10.2019 22:30

DVV,
нет data?
тогда
data && data.forEach(coin => { ...

laimas 25.10.2019 22:31

Цитата:

Сообщение от DVV
а как?

Ну как, через CSS ячейке этой определите цвет зеленый, а далее как рони прописал, добавляя или нет имя класса, при наличии которого цвет ее будет красный.

DVV 25.10.2019 22:33

function exchangeDataShow() {
        fetch('https://api.coinmarketcap.com/v1/ticker/?limit=20')
        .then( (responce) => {
            return responce.json();
        })
        .then( (data) => {
            let output = ' ';
            
            data && data.forEach(coin => {
                let rateChangeHour = coin.percent_change_1h < 0 ? 'rate-red' : 'rate-green';
                let rateChangeDay = coin.percent_change_24h < 0 ? 'rate-red' : 'rate-green';
                let rateChangeWeek = coin.percent_change_7d < 0 ? 'rate-red' : 'rate-green';
                output += `
                    <tr>
                        <td>${coin.rank}</td>
                        <td>${coin.name}</td>
                        <td>${coin.price_usd}</td>
                        <td>${coin['24h_volume_usd']}</td>
                        <td>${coin.market_cap_usd}</td>
                        <td>${coin.total_supply}</td>
                        <td>${coin.max_supply}</td>
                        <td class="${rateChangeHour}">${coin.percent_change_1h}%</td>
                        <td class="${rateChangeDay}">${coin.percent_change_24h}%</td>
                        <td class="${rateChangeWeek}">${coin.percent_change_7d}%</td>
                    </tr>
                `; 
            });

            document.getElementById('market-data').innerHTML = output;
            
        })
        .catch( (err) => {
            console.log(err);
        });
    }

    window.onload = exchangeDataShow();

    setInterval(() => {
        console.log('reload');
        exchangeDataShow();
    }, 5000);


null все равно выводится

DVV 25.10.2019 22:35

Сделал, через тернарный оператор получилось

DVV 25.10.2019 22:36

А это куда прописывать?

рони 25.10.2019 22:42

laimas,
можно код?

laimas 25.10.2019 22:44

Цитата:

Сообщение от рони
можно код?

Чего?

рони 25.10.2019 22:44

DVV,
<td>${coin.max_supply||""}</td>

рони 25.10.2019 22:45

Цитата:

Сообщение от laimas
Ну как, через CSS ячейке этой определите цвет зеленый, а далее как рони прописал, добавляя или нет имя класса, при наличии которого цвет ее будет красный.

не понимаю

рони 25.10.2019 22:47

DVV, или так
<td>${coin.max_supply === null ? "" : coin.max_supply }</td>

laimas 25.10.2019 22:50

Цитата:

Сообщение от рони
не понимаю

А что непонятного, зачем два имени класса, если ячейка может иметь один из двух цветов. Значит определить этим ячейкам сразу зеленый цвет - nth-child(exp), а класс определяющий красный цвет добавлять по условию.

рони 25.10.2019 23:10

laimas,
алгоритм понятен, но я думал это как-то сократит код.

Malleys 26.10.2019 01:51

Цитата:

Сообщение от рони
<td>${coin.max_supply||""}</td>

Если будет 0, то вместо него будет пустая строка


Цитата:

Сообщение от рони
или так
<td>${coin.max_supply === null ? "" : coin.max_supply }</td>

Ну тогда уж определить как обрабатывать шаблон, чтобы нигде не проскочил ни null, ни undefined

Например, так...

function show([head, ...tail], ...substitutions) {
	return tail.reduce((result, template, i) => (
		result + 
		(substitutions[i] == null ? "" : substitutions[i]) +
		template
	), head)
}

laimas 26.10.2019 12:31

Цитата:

Сообщение от рони
я думал это как-то сократит код

Можно было бы и сократить, если бы исходник имел только то, что требуется и в нужном порядке, а далее добавлять в фрагмент ячейки, с двумя условиями: для null значений и с ключами содержащих в имени "percent", для которых classList.toggle('я красный', value < 0).
Либо имел бы JS функции подобные array_intersect_key, можно было бы отсеять "мусор", иначе сокращения не получится. )

PS. То есть, было бы хоть что-то из этого готовое, то по такому принципу:

<style>
table {
    border-collapse: collapse;
}
td, th {
    padding: 5px;
    border: 1px solid #ddd;
}
td:nth-child(n+7) {
    color: #198E01;
}
.red {
    color: #B20101!important;
}
</style>

<table>
<tr>
    <th>Криптовалюта</th>
    <th>Курс</th>
    <th>Обоъем торогов</th>
    <th>Капитализация</th>
    <th>Оборот</th>
    <th>Максимум</th>
    <th>Курс 7ч</th>
    <th>Курс 24ч</th>
    <th>Курс 7д</th>
</tr>
</table>

<script>
fetch('https://api.coinmarketcap.com/v1/ticker/?limit=20')
.then( (responce) => {
     return responce.json();
})
.then( (data) => {
    let tbl = document.querySelector('table'), key = 'name price_usd 24h_volume_usd market_cap_usd total_supply max_supply percent_change_1h percent_change_24h percent_change_7d'.split(' ');
    data && data.forEach(coin => {
        let tr = tbl.insertRow(-1);
        Object.entries(coin).filter(function(v) {
            return key.includes(v[0])
        }).forEach(v => {
            let td = tr.insertCell(-1);
            td.textContent = v[1] || '';
            td.classList.toggle('red', /^percent/.test(v[0]) && v[1]<0)    
        })
    })
})
</script>


Но тут не в том порядке, только лишь нужное.

Malleys 26.10.2019 17:45

Цитата:

Сообщение от laimas
зачем два имени класса, если ячейка может иметь один из двух цветов.

Вы можете указать вместо цвета (числа на самом деле не имеют свойства цвета!) знак числа, что более грамотно с точки зрения математики. В стилях вы сможете тогда более интересные вещи сделать.
#market-data td[data-sign="1"] {
	color: #198E01;
}
#market-data td[data-sign="-1"] {
	color: #B20101;
}


Цитата:

Сообщение от laimas
Значит определить этим ячейкам сразу зеленый цвет - nth-child(exp)

Это ограничивает перестановку столбиков!

Цитата:

Сообщение от laimas
<tr>
    <th>Криптовалюта</th>
    <th>Курс</th>
    <th>Обоъем торогов</th>

Цитата:

Сообщение от laimas
key = 'name price_usd 24h_volume_usd

Вместо того, чтобы объявлять отдельно столбики и связанные с ними ключи, вы можете указать в атрибуте соответствующий ключ, что позволяет легко менять столбики местами.
<tr>
	<th data-key="rank">№</th>
	<th data-key="name">Криптовалюта</th>
	<th data-key="price_usd">Курс</th>

Мы можем в таком случае получать массив с нужными ключами в нужном порядке!

Цитата:

Сообщение от laimas
Можно было бы и сократить, если бы исходник имел только то, что требуется и в нужном порядке

Разве исходник нельзя обработать программно? Если у вас есть массив с нужными ключами в нужном порядке, то вы можете применить функцию map, чтобы отобразить ключи на значения соответствующие этим ключам. Меня удивило, что вы споткнулись на этом! Неужели увлечение PHP так пагубно влияет? Чтобы не мозг не закостенел от PHP, используйте хотя бы иногда Java, C#, Python, или ещё какой язык, и даже JavaScript пойдёт, ведь есть всё-таки node.js! Язык суть средство записи, в первую очередь важно изучать алгоритмы.

Цитата:

Сообщение от laimas
было бы хоть что-то из этого готовое

Всё что нужно, уже есть, вот проверьте...
DVV, вот вам код, в котором нет null и столбики вы можете легко менять!
<style>
	table#market-data {
		border-collapse: collapse;
	}
	#market-data td,
	#market-data th {
		padding: 5px;
		border: 1px solid #ddd;
	}
	#market-data td[data-sign="1"] {
		color: #198E01;
	}
	#market-data td[data-sign="-1"] {
		color: #B20101;
	}
</style>
<table id="market-data">
	<thead>
		<tr>
			<th data-key="rank">№</th>
			<th data-key="name">Криптовалюта</th>
			<th data-key="price_usd">Курс</th>
			<th data-key="24h_volume_usd">Объём торгов</th>
			<th data-key="market_cap_usd">Капитализация</th>
			<th data-key="total_supply">Оборот</th>
			<th data-key="max_supply">Максимум</th>
			<th data-key="percent_change_1h">Курс 7ч</th>
			<th data-key="percent_change_24h">Курс 24ч</th>
			<th data-key="percent_change_7d">Курс 7д</th>
		</tr>
	</thead>
	<tbody></tbody>
</table>
<script>

function exchangeDataShow() {
	fetch('https://api.coinmarketcap.com/v1/ticker/?limit=20')
		.then(response => response.json())
		.then(data => {
			const table = document.getElementById("market-data")
			const keys = Array.from(table.tHead.rows[0].cells, cell => cell.dataset.key)
			const tBody = table.tBodies[0]

			tBody.textContent = ""

			for (const datum of data) {
				const row = tBody.insertRow()

				for (const key of keys) {
					const cell = row.insertCell()
					const value = datum[key]
					cell.textContent = value == null ? "" : value

					if (/^percent/.test(key))
						cell.dataset.sign = Math.sign(value)
				}
			}
		})
}

setInterval(window.onload = exchangeDataShow, 5000)

</script>


ЕЩЁ DVV, слово означающее ответ от сервера по английский пишется как response, laimas, слово объём пишется именно как объём. А вы думали, я не нацист!

laimas 26.10.2019 17:51

Цитата:

Сообщение от Malleys
Разве исходник нельзя обработать программно?

Разве кто-то говорил иное? В том то и дело, что приходится как либо выкручиваться, а речь шла о "сократить".

рони 26.10.2019 18:00

:write:
value == null || (cell.textContent = value);

Malleys 26.10.2019 18:00

Цитата:

Сообщение от laimas
В том то и дело, что приходится как либо выкручиваться

Зачем выкручиваться? Вы получаете данные и вставляете их в таблицу в соответствии с столбиками, разве сервер должен знать о столбиках в интерфейсе?

Тем более вы можете захотеть реализовать перетаскивание столбиков, а также скрывать некоторые из них, так что это нормально данные отобразить программно!

laimas 26.10.2019 18:07

Цитата:

Сообщение от Malleys
Вы получаете данные и вставляете их в таблицу в соответствии с столбиками

Да хоть в горошек, код от этого не стал меньше. Если бы лично я выбирал, то я бы в данном случае не стал бы вставлять html в ... Но разговор был не об этом, так что не зачем мне что-то доказывать.

laimas 26.10.2019 18:23

Malleys,
а так да, на все 100 согласен с тем о чем вы говорите.


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