카테고리 없음

(JS) Combobox (선택도하고, 입력도하고)

안자바먹지 2021. 3. 5. 15:39
728x90

새로 배운 점

CSS의 keyframes 다시 상기

 

 

소스

 

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./style.css" />
    <title>Combo Box</title>
</head>

<body>
    <span class="CurrentItem">현재 아이템:</span>
    <div class="ComboBox">
        <input type="text" />
        <img src="./arrow-down.svg" alt="arrow down" />
        <ul class="ComboBox__list"></ul>
    </div>
    <span class="Notification">아이템이 추가되었습니다.</span>
    <script src="./index.js"></script>
</body>

</html>

 

const ITEM_ADDED_EVENTNAME = 'itemAdded'
const items = []
let currentItem = null
const $currentItem = document.querySelector('.CurrentItem')
const $inputTag = document.querySelector('.ComboBox input')
const $arrowDown = document.querySelector('.ComboBox img')
const $notification = document.querySelector('.Notification')
const $itemList = document.querySelector('.ComboBox__list')

const toggleItemList = () => {
  $itemList.style.visibility =
    $itemList.style.visibility === 'visible' ? 'hidden' : 'visible'
}

$inputTag.addEventListener('keyup', (event) => {
  // Do Something here!
  const { value } = event.target

  if (!value || !value.trim()) {
    return
  }

  if (event.key === 'Enter') {
    items.push(value)
    $inputTag.value = ''
    $itemList.innerHTML = items
      .map((item) => {
        return `<li>${item}</li>`
      })
      .join('')

    document.dispatchEvent(new CustomEvent(ITEM_ADDED_EVENTNAME))
  }
})

$arrowDown.addEventListener('click', () => {
  toggleItemList()
})

$itemList.addEventListener('click', (event) => {
  if (event.target.nodeName !== 'LI') {
    return
  }

  const currentValue = event.target.innerText

  $inputTag.value = currentValue
  $currentItem.textContent = `현재 아이템 : ${currentValue}`
  toggleItemList()
})

document.addEventListener(ITEM_ADDED_EVENTNAME, () => {
  $notification.classList.add('Notification--show')
  $notification.classList.remove('Notification--hide')

  setTimeout(() => {
    $notification.classList.add('Notification--hide')
    $notification.classList.remove('Notification--show')
  }, 3000)
})

 

* {
    box-sizing: border-box;
}

.CurrentItem {
    display: block;
    text-align: center;
    margin-top: 50px;
}

.ComboBox {
    position: relative;
    display: flex;
    margin: 50px auto 0 auto;
    width: 150px;
    height: 30px;
}

.ComboBox input {
    width: 130px;
    height: 100%;
}

.ComboBox img {
    width: 20px;
    height: 100%;
    cursor: pointer;
    border: 1px solid black;
    border-left: none;
}

.ComboBox img:hover {
    background-color: cornsilk;
}

.ComboBox__list {
    position: absolute;
    bottom: -100px;
    display: flex;
    flex-direction: column;
    list-style: circle;
    width: 100%;
    height: 100px;
    margin: 0;
    padding: 0;
    visibility: hidden;
    overflow-x: scroll;
    border: 1px solid black;
}

.ComboBox__list li {
    cursor: pointer;
}

.ComboBox__list li:hover {
    background-color: ivory;
}

.Notification {
    position: absolute;
    top: 10px;
    right: -212px;
    padding: 10px 20px;
    border-radius: 5px;
    font-size: 15px;
    font-weight: 600;
    color: white;
    background-color: deepskyblue;
}

.Notification--show {
    animation: showSlide 1s ease forwards;
}

.Notification--hide {
    animation: hideSlide 1s ease forwards;
}

@keyframes showSlide {
    0% {
        transform: translateX(-30px);
    }

    15% {
        transform: translateX(-250px);
    }

    100% {
        transform: translateX(-222px);
    }
}

@keyframes hideSlide {
    0% {
        transform: translateX(-222px);
    }

    15% {
        transform: translateX(-250px);
    }

    100% {
        transform: translateX(212px);
    }
}
728x90