Эта серия руководств предназначена в качестве заметок для участников семинара, который будет проходить в OKE Software Poland. Предполагается, что участники имеют очень базовое представление о технологиях HTML, CSS и JS. Он не дает сложного обзора текущего состояния интерфейса, а скорее должен рассматриваться как поощрение к дальнейшему получению знаний, необходимых для того, чтобы стать фронтенд-разработчиком или автоматизированным тестировщиком.
План — Поиск билетов, Ваши билеты, интеграция с localStorage
Мы начнем с добавления возможности фильтровать наш список билетов по городу или имени исполнителя.
Затем мы создадим второе представление нашего приложения для тикетов, в котором отображается список пользовательских тикетов. Мы будем использовать механизм localStorage для хранения данных о билетах пользователей. Это дизайн, который мы будем использовать в качестве эталона:
Давайте прыгать прямо в!
Фильтрация наших данных
У нас есть ввод на месте, а также кнопка search
. Разобьем на части:
- мы можем повторно использовать функцию, которая у нас уже есть для рендеринга строк. Это функция, которую мы передаем
map
в таблице js. - мы можем сделать наш код немного более читабельным, если выделим код, ответственный за создание
input
для количества билетов, а такжеbutton
для добавления билетов в список. - Когда пользователь нажимает поиск
button
, мы берем то, что находится вinput
, и используем его для фильтрации наших данных и вызова функции, которая снова отображает строки.
Кажется легко!
Хорошо, давайте возьмем код из функции map
и извлечем его. Мы также можем извлечь функции button
и input
:
Теперь это читается очень хорошо! А теперь к поиску! В папке js
создайте файл searchHeader.js
и добавьте его в index.html в теге <script>
. Хорошо, давайте попробуем получить наши input
и button
с помощью getElementsByName:
Проблема в том, что, как вы можете понять по множественному числу в названии функции, она возвращает массив элементов, тогда как мы хотели бы получить только первый элемент этого массива. Нет проблем, просто возьмем их по первому индексу [0]
:
Хорошо, теперь мы можем добавить прослушиватель событий на наш button
:
И тогда мы можем фильтровать наши данные. Переменная DATA
, а также функция создания строк доступны глобально благодаря привязке глобальный контекст.
Итак, теперь к самой функции. Придется сделать несколько вещей:
- создайте новый набор строк таблицы, отфильтровав
DATA
и сопоставив результат. - Удалите старые строки из таблицы, потому что мы хотим отображать только отфильтрованные.
- Если есть какие-либо строки, являющиеся результатом фильтрации, мы должны их отобразить.
- Если билетов на основе
searchTerm
нет, то мы хотели бы отобразить информацию об этом пользователю.
Хорошо, давайте обработаем 3 первых пункта:
Хорошо, фильтрация работает хорошо! Мы также получаем красивое и блестящее сообщение об ошибке в консоли, когда нет билетов. Теперь давайте добавим информацию об этом. Я создам небольшую вспомогательную функцию insertAfter
, которая поможет мне в этом. В этой функции мы возьмем два узла DOM, один для вставки после второго:
function insertAfter(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); }
Итак, мы можем написать это так:
Затем в ticket-table.css
мы можем добавить наш класс 'no-ticket-warning'
. Нравится:
.no-ticket-warning { text-align: center; color: rebeccapurple; }
Ваши билеты
Итак, теперь мы должны подумать о добавлении, отображении, удалении и оплате наших билетов. Если бы мы создавали настоящее приложение, мы бы, вероятно, использовали базу данных для хранения наших билетов, а затем использовали какой-то API для их добавления, получения и удаления. Для простоты мы будем использовать localStorage. Это словарь, который мы можем использовать для хранения некоторых данных в клиентской части сети. Он сохраняется после закрытия браузера и идеально подходит для хранения идентификаторов, суммы и статуса билета, который пользователь хочет купить.
Мы будем использовать функционал билетов через 2 из 3 наших экранов, поэтому было бы неплохо иметь все это в отдельном файле. Давайте создадим ticketService.js
в нашей папке js
. Это инкапсулирует нашу интеграцию с localStorage
. Первое, что мы хотели бы сделать, это возможность добавлять определенное количество клиентов с заданным идентификатором.
Итак, учитывая, что у нас есть эта служба (которую мы пока не реализовали), мы хотели бы сделать, когда пользователь нажимает кнопку, добавляет нужное количество билетов с правильным идентификатором в localStorage, но как получить это информация с событием клика пользователя?
Начнем с информации о количестве билетов. Мы можем найти вход, который находится рядом с нашей кнопкой. Все слушатели событий в своей функции обратного вызова получают аргумент event
бесплатно. Этот объект имеет свойство target
, указывающее нам на элемент, вызвавший срабатывание слушателя. Target
— это узел DOM, поэтому он имеет свойства previousSibling
и nextSibling
. Их можно использовать для поиска элементов на одном уровне дерева DOM. Поскольку previousSibling
нашего add button
является нашим input
, мы можем легко получить его значение.
А как насчет id
билета? Это немного сложнее, но мы можем получить его с помощью пользовательского атрибута html
. Мы уже знаем атрибуты, например class
для привязки узла html к стилю css. Мы также можем использовать атрибуты для хранения некоторых простых данных, специфичных для данной строки. В нашем случае это будет id
данного билета:
Изменения находятся в строках 18, 19 и 28. Итак, это дает нам возможность вызвать службу ticketService, чтобы добавить кликнутый билет в localStorage
.
Хорошо, теперь мы можем, наконец, заняться написанием нашего ticketService. Давайте начнем с самых основных функций добавления билетов на localStorage
. Мы будем использовать JSON.stringify
, который преобразует объект в строковую нотацию JSON. Это поможет нам на самом деле увидеть, что мы держим в нашем localStorage
. Мы также можем инкапсулировать эти функциональные возможности в объект только для предоставления контекста, пространства имен и предотвращения коллизий имен:
Мы можем использовать инструменты разработчика в Chrome, чтобы проверить, действительно ли мы добавили наши данные в localStorage:
Пока мы добавляем тикет, не хватает нескольких вещей:
- Если кто-то добавляет билеты с
id
, которые уже есть вlocalStorage
, мы хотели бы увеличить количество билетов вместо того, чтобы вставлять новый номер - Когда кто-то выбирает другой билет, мы не хотим переопределять текущий, а добавляем его в массив билетов.
Теперь рассмотрим первый случай:
Здесь мы находим индекс в массиве наших билетов, а затем обновляем количество билетов в этом массиве. В JS есть слабые типы, поэтому мы должны быть уверены, что на самом деле добавляем числа вместо строк. Вот почему мы используем parseInt
для получения количества билетов. Мы также добавляем parseInt
при добавлении билетов в table.js
:
ticketService.addTicket(ticketId, parseInt(ticketAmount));
Хорошо, последний случай теперь довольно прост. Если у нас нет тикета данного id
в массиве, запихиваем новый тикет в массив ticket:
Мои билеты
Итак, теперь мы можем перейти к созданию следующего представления. Мы снова начнем с заголовка. Давайте настроим базовую разметку для нашего сайта и шапки:
https://gist.github.com/wojciech-bilicki/7a1a1776d579c6456a39fbbe0f3b41db
Хорошо, мы уже можем видеть, что это выглядит довольно красиво. Мы повторно используем стили, определенные ранее, но они потребуют некоторой настройки. Начнем с настройки текста заголовка и кнопок:
Мы должны избавиться от стандартного свойства кнопки background-image
, чтобы заменить его нашим background-color
. Также мы устанавливаем margin-left:auto
на наш pay-button
, чтобы вытолкнуть его из нашего текста заголовка h1
. Хорошо, теперь мы можем добавить нашу таблицу и метки заголовков:
Довольно прямолинейно, поскольку мы уже сделали это на нашей главной / домашней странице. Стоит отметить, что теперь у нас есть раздел Actions
, в котором мы будем хранить несколько дополнительных кнопок для каждой строки. Давайте теперь перейдем к JS, чтобы фактически отобразить наши строки. Давайте создадим файл ticketList.js
и добавим его вместе с файлом DATA.js
:
Хорошо, теперь давайте подумаем, как бы мы хотели, чтобы наши данные загружались:
- Если в
localStorage
нет данных, мы хотели бы сообщить нашему пользователю, что он еще не выбрал билеты. - Мы будем использовать данные, хранящиеся в
localStorage
, чтобы определить, какие билеты должны отображаться в таблице «Мои билеты». Мы будем использоватьmap
и фильтровать доachieve
этого.
Давайте начнем просто писать в нашем ticketList.js
:
Конечно, у нас еще нет реализованной функции getMyTickets
, поэтому давайте перейдем к ticketService
и напишем ее:
Здесь нет ничего сложного. Мы анализируем сохраненные билеты, чтобы превратить их в массив JS.
Затем мы сопоставляем их, чтобы создать объекты, которые мы хотели бы отобразить в нашем списке заявок. Мы находим подходящее событие/концерт для данного билета, отфильтровывая массив DATA, и добавляем в билет необходимые свойства. В конце мы возвращаем из функции массив наших тикетов.
Что я хотел бы сделать сейчас, так это написать функцию createRow
для нашего ticketList
, но у нас уже есть одна функция, которая вызывается точно так же, и у нас не может быть двух функций с одинаковыми именами, потому что они перекрывают друг друга. Поэтому мы добавим еще одно пространство имен, чтобы решить эту проблему:
И мы можем правильно заполнить наш ticketList.js
. Он будет похож на наш table.js
:
Единственное отличие, о котором стоит упомянуть, это то, как мы используем функцию map
. Мы передаем this
(одна из самых запутанных вещей в JS), поэтому позже мы можем вызвать this.createActionButtons
. В этом (ахахахахах стоп) конкретном примере this
указывает на наш ticketList
объект/пространство имен, в котором мы вызываем эти функции. Я рекомендую вам прочитать больше об этом:
Ясно понять «это в JavaScript и освоить его
Необходимое условие: немного JavaScript. Продолжительность: около 40 минут. Ключевое слово this в JavaScript путает новых и опытных…javascriptissexy.com»
Хорошо, что осталось сделать, это применить некоторые стили, чтобы наша таблица билетов выглядела красиво. Мы будем ленивы и просто добавим id="ticket-table"
и повторно используем все наши стили из предыдущей таблицы.
Нам осталось стилизовать наши кнопки pay
и delete
. Мы начнем с использования свойства classList
узла DOM, чтобы добавить соответствующие классы для наших кнопок:
https://gist.github.com/wojciech-bilicki/bcbcfbb55f65111c6f85c157969141f9
И тогда мы на самом деле запишем их внутри table.css
:
Хорошо, это пока все. В следующей части мы обработаем случай с пустым состоянием и подключим прослушиватели событий ко всем нашим кнопкам в My Tickets List! Ваше здоровье!