Допилить задание, чтобы как-то так выглядело, когда тыкаешь на строчки
- чтобы картинку заменять, надо добавить
img
с пустым атрибутомsrc
и из скрипта устанавливать атрибут картинки на значениеrow.dataset.image
Сегодня попробуем запилить табличку. В ней буду выводить информацию по фильмам, а по нажатию на строку буду выдавать более подробную информацию в блок рядом с табличкой.
Начнем со стандартной вёрстки:
<!doctype html>
<html lang="en">
<head>
<title>Title</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
теперь определюсь с данными. У меня буду такой список:
Название | Год выпуска | Рейтинг кинопоиска | URL с обложкой, с кинопоиска | Режиссер |
---|---|---|---|---|
Унесённые призраками | 2001 | 8.4 | https://avatars.mds.yandex.net/get-kinopoisk-image/1629390/64becb5d-e7b9-4a56-8c71-5008294a854a/300x450 | Хаяо Миядзаки |
Малхолланд Драйв | 2002 | 7.6 | https://avatars.mds.yandex.net/get-kinopoisk-image/1777765/477bd555-16ee-47aa-be90-6a252c189414/300x450 | Дэвид Линч |
Мертвец | 1995 | 7.8 | https://avatars.mds.yandex.net/get-kinopoisk-image/1773646/707e78dc-43a0-4309-88f0-dee4ce7a4e57/300x450 | Джим Джармуш |
в табличку я буду выводить только название и рейтинг. Остальное буду выводить, когда буду тыкать на строки. Собственно, как ее добавить?
Для этого надо минимально прописать следующие теги:
<div class="container">
<table>
<thead>
<tr>
<th>Название</th>
<th>Рейтинг</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
на картинке красным я выделил область заголовка таблицы (это как правило первая строка), внутри этой области оранжевым выделено собственно само объявление строки (тег tr
), ну и синим выделены собственно теги ячеек th
, так как у меня в строке две ячейки то и тега две штуки.
если посмотреть, то будет выглядеть вот так:
выглядит уродливо, но это потому что мы не добавили классы bootstrap.
Добавим табличке класс table
<div class="container">
<table class="table">
<thead>
<tr>
<th>Название</th>
<th>Рейтинг</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
от теперь другое дело, таблица сразу респонсивная:
теперь добавим данных. Данные как ты, наверное, уже догадалась пишутся внутрь тега tbody.
На каждую строку данных надо добавлять сначала тег tr
, а потом внутри него прописывать теги td
для каждой ячейки. Тут небольшой тонкий момент, для ячеек заголовка используем тег th
, а для ячеек, данных используем td
, так принято, но на самом деле можно и там и сям использовать и тот и этот тег. Просто th
выделяет текст жирным.
Добавлю строчку:
<div class="container">
<table class="table">
<thead>
<!-- ... -->
</thead>
<tbody>
<tr>
<td>Унесённые призраками</td>
<td>8.4</td>
</tr>
</tbody>
</table>
</div>
и еще парочку:
<table class="table">
<thead>
<!-- ... -->
</thead>
<tbody>
<tr>
<!-- ... -->
</tr>
<tr>
<td>Малхолланд Драйв</td>
<td>7.6</td>
</tr>
<tr>
<td>Мертвец</td>
<td>7.8</td>
</tr>
</tbody>
</table>
посмотрим что нам предлагает для таблиц bootstrap: https://getbootstrap.com/docs/4.6/content/tables/ . Посмотри какие классы ты хочешь себе добавить. Главное обязательно добавь класс table-hover
чтобы при наведении на строку она выделялась, я добавлю себе еще темный заголовок:
<div class="container">
<table class="table table-hover">
<thead class="thead-dark"> <!-- темный заголовок сделал -->
<!-- ... -->
</thead>
<tbody>
<!-- ... -->
</tbody>
</table>
</div>
получится так
чтобы при наведении на строку курсор выглядел как указательный палец добавим класс со стилем, вот такой:
<style>
.table tr td:hover { /* :hover -- это псевдо класс, добавляется когда наводишь на элемент мышку */
cursor: pointer; /*курсор -- указатель*/
}
</style>
вообще наверное и td:hover хватило, но так точнее.
Теперь подумаем, что делать с остальными данными? Надо их как-то привязать к строкам, но так чтобы юзер их не видел. Для этого есть так называемые дата атрибуты, их можно добавлять к любому элементу, и они начинаются со слова data-
, а дальше любое свое слово.
Например, добавлю я год выпуска, делается это так:
<div class="container">
<table class="table table-hover">
<thead class="thead-dark">
<!-- ... -->
</thead>
<tbody>
<tr data-year="2001"> <!-- добавил data-year -->
<td>Унесённые призраками</td>
<td>8.4</td>
</tr>
<tr data-year="2002"> <!-- и тут-->
<td>Малхолланд Драйв</td>
<td>7.6</td>
</tr>
<tr data-year="1995"> <!-- и здесь -->
<td>Мертвец</td>
<td>7.8</td>
</tr>
</tbody>
</table>
</div>
так как их не видно, то сделаны они специально чтобы js их использовал, добавим функцию:
<script>
function onRowClick(row) {
console.log(row);
}
</script>
подключим ее к строкам:
<div class="container">
<table class="table table-hover">
<thead class="thead-dark">
<!-- ... -->
</thead>
<tbody>
<tr data-year="2001" onclick="onRowClick(this)">
<!-- ... -->
</tr>
<tr data-year="2002" onclick="onRowClick(this)">
<!-- ... -->
</tr>
<tr data-year="1995" onclick="onRowClick(this)">
<!-- ... -->
</tr>
</tbody>
</table>
</div>
проверим что все работает:
теперь собственно, как получить доступ к этим атрибутам? А очень просто, у всякого элемента при работе с ним в js есть свойство dataset
и вот в него эти атрибуты и попадают, подправим функцию:
<script>
function onRowClick(row) {
console.log(row.dataset);
}
</script>
проверяем:
то есть, чтобы вывести год привязанный к строке, надо написать так:
<script>
function onRowClick(row) {
console.log(row.dataset.year);
}
</script>
тыкаем:
добавим теперь оставшиеся наши данные в атрибуты, режиссера я буду пихать в data-director
, а картинку в data-image
, вот так:
<div class="container">
<table class="table table-hover">
<thead class="thead-dark">
<!-- ... -->
</thead>
<tbody>
<tr data-year="2001" data-director="Хаяо Миядзаки" data-image="https://avatars.mds.yandex.net/get-kinopoisk-image/1629390/64becb5d-e7b9-4a56-8c71-5008294a854a/300x450" onclick="onRowClick(this)">
<!-- ... -->
</tr>
<tr data-year="2002" data-director="Дэвид Линч" data-image="https://avatars.mds.yandex.net/get-kinopoisk-image/1777765/477bd555-16ee-47aa-be90-6a252c189414/300x450" onclick="onRowClick(this)">
<!-- ... -->
</tr>
<tr data-year="1995" data-director="Джим Джармуш" data-image=" https://avatars.mds.yandex.net/get-kinopoisk-image/1773646/707e78dc-43a0-4309-88f0-dee4ce7a4e57/300x450" onclick="onRowClick(this)">
<!-- ... -->
</tr>
</tbody>
</table>
</div>
вообще если так подумать есть смысл туда запихать и название, и рейтинг:
<!-- ... -->
<tr data-title="Унесённые призраками" data-rating="8.4" data-year="2001" data-director="Хаяо Миядзаки" data-image="..." onclick="onRowClick(this)">
<td>Унесённые призраками</td>
<td>8.4</td>
</tr>
<tr data-title="Малхолланд Драйв" data-rating="7.6" data-year="2002" data-director="Дэвид Линч" data-image="..." onclick="onRowClick(this)">
<td>Малхолланд Драйв</td>
<td>7.6</td>
</tr>
<tr data-title="Мертвец" data-rating="7.8" data-year="1995" data-director="Джим Джармуш" data-image="..." onclick="onRowClick(this)">
<td>Мертвец</td>
<td>7.8</td>
</tr>
<!-- ... -->
Теперь добавим блок справа куда я буду выводить подробную информацию. Для этого запихаем таблицу в строку,
<div class="container">
<div class="row">
<div class="col-8">
<table class="table table-hover">
<!-- ... -->
</table>
</div>
<div class="col-4">
<!-- ... -->
</div>
</div>
</div>
получится так, вот справа видно колонку если ее из инспектора выделить
то есть таблица занимает 8/12 а табличка 4/12. Добавим туда что-нибудь с рамочкой
<div class="container">
<div class="row">
<div class="col-8">
<table class="table table-hover">
<!-- ... -->
</table>
</div>
<div class="col-4">
<div class="shadow p-2 text-center">
Название
</div>
</div>
</div>
</div>
полчится так:
глянем как работают медиа классы, то есть которые меняют расположение элементов в зависимости от ширины экрана. Я хочу, чтобы, например, на большом экране от 768px в ширину у меня все было как сейчас, табличка 8/12, а название 4/12. Для этого я меняю класс col-8
на col-md-8
, а col-4
на col-md-4
,
<div class="container">
<div class="row">
<div class="col-md-8">
<table class="table table-hover">
<!-- ... -->
</table>
</div>
<div class="col-md-4">
<div class="shadow p-2 text-center">
Название
</div>
</div>
</div>
</div>
а теперь глянем как себя поведет верстка если мы начнем менять размеры экрана:
то есть для размеров которые меньше 768 он делает так чтобы элемент занимал всю ширину. Я не буду сильно на этом останавливаться, но если научится оперировать этими модификаторами (типа md
, там есть еще xl
, lg
, sm
), то можно делать сайт который будет удобно смотреть и на десктопе, и на телефоне.
В бутстрапе у многих классов есть их версия с md
, что позволяет очень гибко настраивать поведение. Например, у того же отступа можно для больших дисплеев использовать отступ p-md-2
, а для телефонов, например, уменьшать p-sm-1
, в общем, тьма возможностей =)
Сделаем теперь чтобы при клике на row у нас текст менялся на название фильма.
Обернем Название в тег span и добавим ему id:
<!-- ... -->
<div class="col-md-4">
<div class="shadow p-2 text-center">
<span id="title">Название</span>
</div>
</div>
а теперь как обычно подправим функцию так чтобы она меняла текст title на дата атрибут нашей строки, вот так:
<script>
function onRowClick(row) {
let title = document.getElementById("title")
title.innerText = row.dataset.title;
}
</script>
теперь сделаем еще так чтобы при клике на строку она фиксировалась как выделенная. Чтобы выделить строку при клике на нее я буду добавлять класс table-info
(больше классов тут https://getbootstrap.com/docs/4.6/content/tables/#contextual-classes)
<script>
function onRowClick(row) {
let title = document.getElementById("title")
title.innerText = row.dataset.title;
row.classList.add("table-info");
}
</script>
смотрим:
строки выделяются, но не сбрасываются цвета у предыдущих. Вот и вопрос как сделать сброс?
Можно завести переменную в которую будем фиксировать предыдущую строку, и при клике на очередную строку, у предыдущей будем удалять класс, вот так:
<script>
let previousRow = null; // завел переменную под строку
function onRowClick(row) {
let title = document.getElementById("title")
title.innerText = row.dataset.title;
if (previousRow) { // если предыдущая строка не пустая
previousRow.classList.remove("table-info") // то удаляем у нее класс
}
row.classList.add("table-info");
previousRow = row; // меняем предыдущую строку на текущую
}
</script>
проверка:
Более дубовый но более унивесальный, и чаще используется, просто удаляем класс у всех строк, и добавляем класс текущей
<script>
function onRowClick(row) {
let title = document.getElementById("title")
title.innerText = row.dataset.title;
// находим все теги tr, которые внутри tbody, который внутри тега с классом table
document.querySelectorAll(".table tbody tr").forEach(el => {
el.classList.remove("table-info"); // удаляем у них класс table-info
})
row.classList.add("table-info");
}
</script>
работает так же:
Ну база есть, теперь иди пили задачку =)
Допилить задание, чтобы как-то так выглядело, когда тыкаешь на строчки
img
с пустым атрибутом src
и из скрипта устанавливать атрибут картинки на значение row.dataset.image