Часть 2 — подборка мемов Purrfect от Pumpkin

Следующий проект в модуле Essential Java Script — создать генератор кошачьих мемов, который будет извлекать объект из массива в зависимости от настроения, которое выбирает пользователь. Объект будет содержать изображение, связанное с настроением, и будет отображать мем в модальном окне. Концепция довольно проста, но мы начинаем изучать некоторые действительно мощные инструменты, которые JavaScript может предоставить разработчику.

Вот фрагмент массива, который нам нужно будет пройти, чтобы отобразить мем:

const cats = [
  {
    emotionTags: ["sad"],
    isGif: false,
    image: "sad.jpeg",
    alt: "A cat looking sad",
   },
   {
    emotionTags: ["sad", "moody"],
    isGif: false,
    image: "sad1.jpeg",
    alt: "A cat looking sad",
    } ...
]

1. Циклы for of

Первый инструмент, с которым мы сталкиваемся, — это еще один цикл. Ранее мы изучили и использовали циклы for для повторения некоторого блока кода определенное количество раз. Хотя мы могли бы использовать этот код, мы перебираем массив, содержащий объекты, поэтому для того, чтобы мы могли получить доступ к img в объекте, нам потребуется много беспорядочного кода в обычном цикле for.

Здесь пригодится цикл for of. Давайте посмотрим на синтаксис этого цикла:

for(let cat of cats) {
 ...
}  

Цикл for of будет проходить через массив «cats» и выделять каждый объект, который находится в массиве, чтобы вы могли получить доступ к различным свойствам в этом массиве. Следовательно, мы могли бы отобразить тег alt каждого объекта cat, написав console.log(cat.alt). Консоль будет отображать каждый тег alt, который был написан для описания каждого кошачьего мема. Теперь мы используем цикл «for of» для доступа к тегам эмоций объекта, но теги эмоций являются массивами. Итак, у нас есть массив, содержащий объекты, содержащие массивы. Чтобы получить доступ к этим эмоциям, нам нужен еще один цикл for of:

for(let cat of cats) {
  for(let emotion of cat.emotionTags){
     ...
  }
}

Цикл for of, вложенный друг в друга, позволяет нам получить доступ к массиву в объекте, чтобы, как я упоминал выше, сохранить код в чистоте. Таким образом, на этом этапе каждая итерация будет обращаться к каждой эмоции в массивеmotionTags для каждого объекта в исходном массиве. Это позволит нам правильно выбрать объект мема, который соответствует эмоции, которую выбирает пользователь.

Вот созданная нами функция под названием getEmotionsArray, которая использовала цикл for of для доступа к тегам эмоций. Если эмоция уже была добавлена ​​в переменную типа эмоции, она пропускалась, чтобы предотвратить повторение.

function getEmotionsArray(cats) {
  const emotionArray = [];
  for(let cat of cats){
    for(let emotion of cat.emotionTags){
      if(!emotionArray.includes(emotion){
        emotionArray.push(emotion)
}  }  }  }

2. Радиовходы

Радиовходы — это один из нескольких типов входов, которые вы можете выбрать при создании формы. О чекбоксах и текстовом вводе мы говорили в прошлой статье (Часть 1). Радиовходы позволяют пользователю выбирать только один вариант из списка, а не иметь несколько вариантов.

<form>
  <input type="radio">
</form>

То, как это связано с JavaScript, делает радио-входы еще более интересными. Вместо того, чтобы вручную записывать каждую эмоцию в HTML, мы вместо этого импортировали массивcatsData и создали функцию, которая отображала список для нас.

Мы обращаемся к функции выше getEmotionsArray, чтобы создать список эмоций без повторов из массиваcatsData. Затем мы визуализируем каждую эмоцию как радиовход с уникальной меткой, идентификатором, именем и значением.

function renderEmotionsRadio(array){
  const emotions = getEmotionsArray(array)
  let radioItems = '';
  for(let emotion of emotions){
      radioItems += `
          <div class="radio">
              <label for="${emotion}">${emotion}</label>
              <input 
                  type="radio" 
                  value="${emotion}" 
                  id="${emotion}" 
                  name="emotion-choice"
              >
          </div>`
  }
  
  emotionContainer.innerHTML = radioItems
}

renderEmotionsRadio(catsData)

3. включает метод

.includes() — это встроенный метод JavaScript, который позволяет разработчику указать параметр, например, someArray.includes(‘apples’). Метод будет искать каждый элемент в массиве и возвращать true, если этот массив содержит параметр. Это полезно, поскольку позволяет поддерживать неизменяемый массив, что означает, что массив не будет изменен. Используя .includes с .push, мы можем создать массив, полный эмоций, которые соответствуют различным мемам в нашем массиве, но без повторяющихся вариантов эмоций.

4. event.target.id

В предыдущей статье мы обсуждали события, когда нам нужно было предотвратить поведение браузера по умолчанию. В этом проекте мы делаем события на шаг впереди и используем их как способ ограничить количество прослушивателей событий и поддерживать чистоту кода (вы можете заметить закономерность в этом проекте). Используя e.target.id, мы можем получить идентификатор элемента, который активировал прослушиватель событий, и далее манипулировать этим конкретным элементом. В противном случае без e.target.id нам пришлось бы создавать addEventListeners для каждой эмоции радиоэлемента, доступной на экране.

В частности, мы используем e.target.id для возврата идентификатора радиоэлемента, который выбирает пользователь. Как только этот идентификатор будет возвращен нам, мы сможем активировать стиль CSS, предназначенный для радиоэлемента, на который щелкнул пользователь, но только для активного радиоэлемента. Мы надеемся, что после следующих двух разделов это станет более понятным, так что оставайтесь со мной.

container.addEventListener('click', function(e){
  document.getElementById(e.target.id)...
}

5. родительский элемент

Это следующая часть головоломки, которая свяжет e.target.id, а также поможет понять, как вы можете в дальнейшем манипулировать DOM (объектной моделью документа) с помощью JavaScript. parentElement возвращает родительский элемент элемента, что говорит само за себя.

В средстве выбора мемов вы можете настроить таргетинг на элемент div, содержащий элемент радио, настроив таргетинг на родительский элемент радио, на который нажимает пользователь. См. код ниже, чтобы визуализировать:

function highlightCheckedOption(e){
  document.getElementById(e.target.id).parentElement...
}

6. список классов

Теперь, когда у нас есть доступ к отдельному div, содержащему выбранный пользователем элемент радио, мы можем переключать стиль CSS, который, как мы хотим, вступает в силу только тогда, когда пользователь активно щелкает элемент радио. Это достигается с помощью classList. classList позволяет разработчику получить доступ к разделу классов элемента и даже может изменять классы с помощью таких методов, как add(). Add() позволит вам добавить имя класса к элементу, а затем активировать стиль CSS, о котором я упоминал ранее.

function highlightCheckedOption(e){
  document.getElementById(e.target.id).parentElement.classList.add('highlight')
}

Теперь, когда пользователь выбирает настроение, элемент радио будет выделяться красным фоном, чтобы обозначить его выбор. Одна потенциальная проблема, с которой мы сталкиваемся, заключается в том, что теперь невозможно отключить стиль выделения, и если пользователь выберет другое настроение, предыдущий элемент по-прежнему будет иметь стиль CSS. Мы коснемся этого в следующем разделе.

7. получитьимяэлемента поклассу

Это еще один способ, с помощью которого разработчик может указать элемент в HTML и манипулировать им в JavaScript. Используя .getElementByClassName, вы используете модель документа так же, как мы использовали .getElementById, но с важным отличием. getElementByClassName (назовем его для краткости gEBCN?) вернет массив с каждым элементом, который соответствует имени класса, которое вы ему дали. Это важно, потому что вместо того, чтобы получить один результат по идентификатору, вам придется перебирать массив, чтобы найти все элементы.

В средстве выбора мемов использование этого метода дает нам преимущество, когда речь идет о проблеме, которую мы имели в предыдущем разделе. Когда мы добавили стиль CSS к выбранному элементу с помощью parentElement и classList, у нас возникла проблема, когда пользователь нажимал на другой элемент переключателя, предыдущий элемент сохранял стиль CSS без возможности очистить класс. Используя gEBCN, мы можем перебирать все потенциальные элементы с этим именем класса и удалять стиль CSS, когда пользователь выбирает другой элемент переключателя. Это показано ниже:

function hightlightCheckedOption(e){
  const radioItems = document.getElementByClassName('radio')
  for(let item of radioItems){
    item.classList.remove('highlight')
  }
  ...
}

8. селектор запросов

Еще одна часть средства выбора мемов, помимо выбора эмоции, которую пользователь захочет отобразить, пользователь может решить, хочет ли он, чтобы мем был Gif или нет. Как показано на снимке экрана ниже, флажок создается для возврата логического значения true, если флажок установлен для gif, или false, если флажок пуст.

querySelector — это мощный инструмент, используемый для манипулирования моделью DOM, и работает аналогично getElementByClassName, но с некоторыми важными отличиями. Для целей нашего мем-проекта querySelector позволяет разработчику получить элемент по его псевдоклассу. Псевдокласс — это то, что используется в CSS и нацелено на состояние элемента, например, когда пользователь наводит курсор на кнопку (кнопка: наведение). В проекте мы используем querySelector для нацеливания на флажок, и если он нажат, мы будем фильтровать массив, чтобы возвращать только мемы, которые являются GIF. Во-первых, мы проверяем, установлен ли флажок, чтобы, если он возвращает значение true, мы создавали константу для хранения элемента радио, по которому был сделан щелчок, и использовали его для фильтрации массива для этой эмоции и GIF-файлов.

const gifCheckbox = document.getElementById('gifs-only-option') 
  //This targets the checkbox element in the HTML

funciton getMatchingCatsArray(){
  if(document.querySelector('input[type="radio":checked'){
    const selectedEmotion = 
      document.querySelector('input[type="radio":checked').value
    const isGif = gifCheckbox.checked
    ...
    }    
}

9. Метод фильтрации

Метод filter() — это последняя большая тема, которую нужно изучить в проекте, и она прекрасно сочетается с функцией, которую мы представили выше, getMatchingCatArray. После того, как мы решили, установил ли пользователь флажок «Только GIF» или нет, и после того, как мы нацелились на эмоцию, которую выбрал пользователь, нам нужно теперь пройти через массив и нацелить определенные мемы для возврата. Вот как фильтр может помочь нам найти мемы, соответствующие нашей квалификации. Фильтр будет проходить через каждый элемент в массиве, и если элемент возвращает true для соответствующего параметра, функция скопирует элемент в новый массив. Посмотрите, как код работает в нашем проекте ниже:

const gifCheckbox = document.getElementById('gifs-only-option') 
  //This targets the checkbox element in the HTML

funciton getMatchingCatsArray(){
  if(document.querySelector('input[type="radio":checked'){
    const selectedEmotion = 
      document.querySelector('input[type="radio":checked').value
    const isGif = gifCheckbox.checked

    const matchingCatArray = catsData.filter(cat => {
        if(isGif){
            return cat.emotionTags.includes(selectedEmotion) && cat.isGif
        }else {
            return cat.emotionTags.includes(selectedEmotion)
        }
    })
    return matchingCatArray
    }    
}

Сначала фильтр проверит, хочет ли пользователь мем только в формате GIF или нет. На основе этих возвращаемых данных он просматривает массив и находит все элементы, соответствующие эмоции, которую выбрал пользователь, и возвращает мем, соответствующий эмоции. Как видите, мы используем метод .include() в сочетании с .filter() для сопоставления элементов в массиве и копирования элементов в новый массив.

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