-
Notifications
You must be signed in to change notification settings - Fork 35
[자동완성] #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[자동완성] #169
Changes from all commits
8dbc23f
4f4f240
6eddfad
9ff0265
9f83dbe
df790ed
5213649
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +0,0 @@ | ||
| # javascript-amazon | ||
| 레벨3 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.1/css/all.css" integrity="sha384-v8BU367qNbs/aIZIxuivaU55N5GPF89WBerHoGA4QTcbUjYiLQtKdrfXnqAcXyTv" crossorigin="anonymous"> | ||
| <link rel="stylesheet" href="style.css"> | ||
| </head> | ||
|
|
||
| <body> | ||
|
|
||
| <div class="carousel-wrapper"> | ||
| <div class='carousel__menu'> | ||
| <ul class='menu__list'> | ||
| </ul> | ||
| </div> | ||
| <!-- carousel__container start --> | ||
| <div class="carousel"> | ||
| <div class="carousel__container"> | ||
| <!-- carousel item start--> | ||
| <!-- carousel item end --> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- carousel__container end --> | ||
| <div class="carousel__button--prev"> | ||
| <i class="fas fa-arrow-left"></i> | ||
| </div> | ||
| <div class="carousel__button--next"> | ||
| <i class="fas fa-arrow-right"></i> | ||
| </div> | ||
| </div> | ||
| <script type="module" src="index.js"></script> | ||
| <script src="./prac.js"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| class Carousel { | ||
| constructor (menuData,contentData) { | ||
| this.menuData=menuData; | ||
| this.contentData=contentData; | ||
| this.makingMenuList(); | ||
| this.makingSlider(); | ||
| this.btnHandler(); | ||
| this.count = 0; | ||
| } | ||
| changeLocation (element,index) { | ||
| this.count = index; | ||
| const width = element.children[0].getBoundingClientRect().width; | ||
| element.style.transform = `translateX(${-this.count*width}px)`; | ||
| } | ||
| scaleMenu (element,index) { | ||
| this.count = index; | ||
| Array.from(element.parentNode.children).forEach((element)=>element.style.transform=`scale(0.99)`) | ||
| element.parentNode.children[this.count].style.transform = 'scale(1.1)'; | ||
| } | ||
| btnHandler () { | ||
| const left =document.querySelector('div.carousel__button--prev'); | ||
| const right =document.querySelector('div.carousel__button--next'); | ||
| [left,right].forEach((btn,index)=>{ | ||
| btn.addEventListener('click',()=>{ | ||
| index === 0 ? this.count-- : this.count++; | ||
| if (this.count >3) this.count =0; | ||
| if (this.count<0) this.count =3; | ||
| const el = document.querySelector('.carousel__container'); | ||
| this.changeLocation(el,this.count); | ||
| this.scaleMenu(document.querySelector('.menu__list>li'),this.count); | ||
| }); | ||
| }) | ||
| } | ||
| makingMenuList () { | ||
| const menuConatiner=document.querySelector('.menu__list') | ||
| this.menuData.forEach((data)=>{ | ||
| menuConatiner.innerHTML +=` | ||
| <li><a href='#'>${data}</a></li>` | ||
| }) | ||
| Array.from(menuConatiner.children).forEach((li,index)=>{ | ||
| li.addEventListener('click',()=>{ | ||
| this.scaleMenu(li,index); | ||
| this.changeLocation(document.querySelector('.carousel__container'),index); | ||
| }) | ||
| }) | ||
| } | ||
| makingSlider () { | ||
| const carouselContainer = document.querySelector('.carousel__container'); | ||
| carouselContainer.innerHTML=this.contentData.map((data,index)=>` | ||
| <div class='carousel__contents'> | ||
| <div class='carousel__text'> | ||
| <ul> | ||
| <h3>${data.title}</h3> | ||
| ${data.desc.map((desc)=>`<li>${desc}</li>`).join('')} | ||
| </ul> | ||
| </div> | ||
| <div class='carousel__img'> | ||
| <img src=${data.imgUrl} /> | ||
| </div> | ||
| </div>`).join(''); | ||
| } | ||
| } | ||
|
|
||
| window.addEventListener('DOMContentLoaded',()=>{ | ||
| fetch('./localData.json') | ||
| .then((data)=>data.json()) | ||
| .then((data)=>{ | ||
| const {menuData,contentData}=data; | ||
| const carousel=new Carousel(menuData,contentData); | ||
| }) | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| { | ||
| "menuData" : [ | ||
| "Fast, Free Delivery", | ||
| "Exclusive deals and offers", | ||
| "Prime Originals, movies and TV shows", | ||
| "Over 2 million song ad free" | ||
| ], | ||
| "contentData" : [{ | ||
| "id" : "1", | ||
| "imgUrl" : "https://placedog.net/200/250?id=8", | ||
| "title" :"Enjoy exclusive savings and rewards", | ||
| "desc" : ["Fast, Free Delivery", | ||
| "Exclusive deals and offers","Prime Originals, movies and TV shows","Over 2 million song ad free"] | ||
| },{ | ||
| "id" : "2", | ||
| "imgUrl" : "https://placedog.net/200/250?id=12", | ||
| "title" :"Code Squad is awesome place", | ||
| "desc" : ["Code, Feel JS", | ||
| "Do you want to be Front Engeneer?","Come to us Master,Good People","Waiting For you!"] | ||
| },{ | ||
| "id" : "3", | ||
| "imgUrl" :"https://placedog.net/200/250?id=14", | ||
| "title" :"Learning With practice and enthusiastic people", | ||
| "desc" : ["React to ur Mind", | ||
| "Es6 class is good for you","We will find answer","As we've done so far"] | ||
| },{ | ||
| "id" : "4", | ||
| "imgUrl" : "https://placedog.net/200/250?id=15", | ||
| "title" :"Watching Dog makes inner-peace", | ||
| "desc" : ["It was hard Day.", | ||
| "Do you feel exhausted?","Come to Our good puppy","puppy would be with you"] | ||
| } | ||
| ] | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| * { | ||
| margin: 0; | ||
| padding: 0; | ||
| box-sizing: content-box; | ||
| } | ||
| body { | ||
| font: 16px Arial; | ||
| } | ||
| header { | ||
| padding: 15px; | ||
| display: flex; | ||
| height: 40px; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| background-color: #242F40; | ||
| } | ||
| .logo { | ||
| display: block; | ||
| width: 70px; | ||
| height: 40px; | ||
| } | ||
| .form-container { | ||
| width: 100%; | ||
| display: flex; | ||
| justify-content: center; | ||
| } | ||
| .autocomplete { | ||
| /*the container must be positioned relative:*/ | ||
| position: relative; | ||
| display: inline-block; | ||
| width: 350px; | ||
| } | ||
| input { | ||
| border: 1px solid transparent; | ||
| border-radius: 5px; | ||
| background-color: #f1f1f1; | ||
| padding: 10px; | ||
| font-size: 16px; | ||
| } | ||
| input[type=text] { | ||
| background-color: #f1f1f1; | ||
| width: 94%; | ||
| } | ||
| input[type=submit] { | ||
| background-color: DodgerBlue; | ||
| color: #fff; | ||
| } | ||
| .autocomplete-items { | ||
| position: absolute; | ||
| border: 1px solid #d4d4d4; | ||
| border-bottom: none; | ||
| border-top: none; | ||
| z-index: 99; | ||
| top: 100%; | ||
| left: 0; | ||
| right: 0; | ||
| } | ||
| .autocomplete-items div { | ||
| padding: 10px; | ||
| cursor: pointer; | ||
| background-color: #fff; | ||
| border-bottom: 1px solid #d4d4d4; | ||
| } | ||
| .autocomplete-items div:hover { | ||
| background-color: #e9e9e9; | ||
| } | ||
| .autocomplete-active { | ||
| background-color: DodgerBlue !important; | ||
| color: #ffffff; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
| <link rel="stylesheet" href="search.css"> | ||
| <title>Document</title> | ||
| </head> | ||
| <body> | ||
| <header> | ||
| <div> | ||
| <a href="#" class="logo"></a> | ||
| </div> | ||
| <div class='form-container'> | ||
| <form action="" autocomplete="off"> | ||
| <div class='autocomplete'> | ||
| <input type="text" id='searchBar' name='myCountry' placeholder="Country"> | ||
| </div> | ||
| <input type="submit" value='Search'> | ||
| </form> | ||
| </div> | ||
| </header> | ||
| <script src="./search.js"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| class Search { | ||
| constructor (data,{autoComplete,input}) { | ||
| this.autoComplete = autoComplete; | ||
| this.data = data; | ||
| this.input = input; | ||
| this.autoCompleteItems; | ||
| this.currentTargetIndex=-1; | ||
| this.handleInputChange(); | ||
| this.handleKeyDown(); | ||
| this.closeAllList() | ||
| } | ||
| handleInputChange () { | ||
| this.input.addEventListener('input',(e)=>{ | ||
| const value = this.input.value; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. value와 같은 대명서 이름은 쓰지말고, 구체적인 의미로 이름을 지어보세요. |
||
| if (!value) return; | ||
| const autoCompleteItemsExits = !!document.querySelector('.autocomplete-items'); | ||
| if (autoCompleteItemsExits) { | ||
| this.autoCompleteItems.parentNode.removeChild(this.autoCompleteItems); | ||
| } | ||
| this.autoCompleteItems = document.createElement('div'); | ||
| this.autoCompleteItems.classList.add('autocomplete-items') | ||
| this.autoComplete.appendChild(this.autoCompleteItems); | ||
| const addList =()=>{ | ||
| this.data.forEach((dataValue)=>{ | ||
| if (dataValue.substring(0,value.length).toUpperCase()===value.toUpperCase()) { | ||
| const contentDiv = document.createElement('div'); | ||
| contentDiv.innerHTML=`<strong>${dataValue.substring(0,value.length)}</strong>${dataValue.substring(value.length)}<input type='hidden' value='${dataValue}'>` | ||
| this.autoCompleteItems.appendChild(contentDiv); | ||
| contentDiv.addEventListener('click',(e)=>{ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반복문 안에서 이벤트 등록을 하지 말고, |
||
| this.input.value = e.target.querySelector('input').value; | ||
| }) | ||
| } | ||
| }) | ||
| } | ||
| setTimeout(()=>{ | ||
| addList(); | ||
| },300) | ||
| }) | ||
| } | ||
| closeAllList () { | ||
| document.addEventListener('click',(e)=>{ | ||
| e.preventDefault(); | ||
| const itemContainer=document.querySelector('.autocomplete-items'); | ||
| if (!itemContainer) return; | ||
| if (e.target!==this.input && e.target!==itemContainer ) { | ||
| itemContainer.parentNode.removeChild(itemContainer); | ||
| } | ||
| }) | ||
| } | ||
| handleKeyDown () { | ||
| this.input.addEventListener('keydown',(e)=>{ | ||
| if (e.which === 40) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. which ?? 이건 jquery 에서 제공되는 속성인거 같은데 맞나요? 표준인가...?? |
||
| this.currentTargetIndex++; | ||
| if (!this.autoCompleteItems) return; | ||
| let checkOutOfListIndex=this.currentTargetIndex >= this.autoCompleteItems.children.length; | ||
| if (checkOutOfListIndex) this.currentTargetIndex=0; | ||
| Array.from(this.autoCompleteItems.children).forEach((item)=>{ | ||
| item.classList.remove('autocomplete-active')}); | ||
| let choosedTarget =this.autoCompleteItems.children[this.currentTargetIndex]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this.autoCompleteItems.children 과 같이 반복되는 속성값은 변수로 캐시해서 사용하는 게 어떨까요. |
||
| choosedTarget=this.autoCompleteItems.children[this.currentTargetIndex]; | ||
| choosedTarget.classList.add('autocomplete-active'); | ||
| this.input.value = choosedTarget.querySelector('input').value | ||
| } else if (e.which === 38) { | ||
| this.currentTargetIndex--; | ||
| if (!this.autoCompleteItems) return; | ||
| let checkOutOfListIndex=this.currentTargetIndex < 0; | ||
| if (checkOutOfListIndex) this.currentTargetIndex=this.autoCompleteItems.children.length-1; | ||
| Array.from(this.autoCompleteItems.children).forEach((item)=>{ | ||
| item.classList.remove('autocomplete-active')}); | ||
| let choosedTarget =this.autoCompleteItems.children[this.currentTargetIndex]; | ||
| choosedTarget=this.autoCompleteItems.children[this.currentTargetIndex]; | ||
| choosedTarget.classList.add('autocomplete-active'); | ||
| this.input.value = choosedTarget.querySelector('input').value | ||
| } else if (e.which === 13) { | ||
| e.preventDefault(); | ||
| if (this.currentTargetIndex > -1) { | ||
| this.autoCompleteItems.children[this.currentTargetIndex].click(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. click() 메서드는 뭔가요?? 표준?? |
||
| } | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| window.addEventListener('DOMContentLoaded',()=>{ | ||
| fetch('./searchData.json') | ||
| .then((data)=>data.json()) | ||
| .then((searchData)=>{ | ||
| const targetElement= { | ||
| autoComplete : document.querySelector('.autocomplete'), | ||
| input : document.querySelector('input#searchBar') | ||
| } | ||
| const search = new Search(searchData.data,targetElement); | ||
| }); | ||
| }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "data" :["Korea","Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia & Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Cayman Islands","Central Arfrican Republic","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica","Cote D Ivoire","Croatia","Cuba","Curacao","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kiribati","Kosovo","Kuwait","Kyrgyzstan","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Micronesia","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Myanmar","Namibia","Nauro","Nepal","Netherlands","Netherlands Antilles","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","North Korea","Norway","Oman","Pakistan","Palau","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre & Miquelon","Samoa","San Marino","Sao Tome and Principe","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","South Africa","South Korea","South Sudan","Spain","Sri Lanka","St Kitts & Nevis","St Lucia","St Vincent","Sudan","Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad & Tobago","Tunisia","Turkey","Turkmenistan","Turks & Caicos","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States of America","Uruguay","Uzbekistan","Vanuatu","Vatican City","Venezuela","Vietnam","Virgin Islands (US)","Yemen","Zambia","Zimbabwe"] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handleInputChange 함수 전체를 훑어보면, 들여쓰기가 5단계까지 보입니다.
이 깊이를 줄이는 방법은 무엇인지 생각해보시죠.
함수를 나누는 것도 좋은 방법 중 하나고요.