Feat/add dropdown list via js (#1)
* [feat/add-dropdown-list] Refactoring dropdown list. * Refactoring class Dropdown * [feat/add-dropdown-list] Added bandler(parcler) * Added mouseenter event handling * Fix bug open dropdown and added main.scss * Added private fild and changed methods * Refactoring DropDown * Added placeholder * Added customStyle * Fixed initSelected * Refactored initSelected * Added feature in customize select * featch customStyle complited! * Delited file customStyle.scss Co-authored-by: MaxOvs <rock_maksimus@mail.ru>
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| node_modules | ||||
| dist | ||||
| .parcel-cache | ||||
							
								
								
									
										4796
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										4796
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| { | ||||
|   "name": "dropdown-list", | ||||
|   "version": "0.0.1", | ||||
|   "description": "", | ||||
|   "scripts": { | ||||
|     "start": "parcel ./src/index.html -p 4500 --open", | ||||
|     "build": "parcel build ./src/index.html" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git+https://github.com/MaxOvs19/Dropdown-list.git" | ||||
|   }, | ||||
|   "author": "", | ||||
|   "license": "ISC", | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/MaxOvs19/Dropdown-list/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/MaxOvs19/Dropdown-list#readme", | ||||
|   "devDependencies": { | ||||
|     "@parcel/transformer-sass": "^2.7.0", | ||||
|     "parcel": "^2.7.0", | ||||
|     "prettier": "^2.7.1" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										205
									
								
								src/cg-dropdown.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/cg-dropdown.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,205 @@ | ||||
| export class DropDown { | ||||
|   #element; | ||||
|   #list; | ||||
|   #options; | ||||
|   #caret; | ||||
|  | ||||
|   //ToDo: Added  url | ||||
|  | ||||
|   constructor(options = {}) { | ||||
|     this.#init(options); | ||||
|     this.#initSelected(); | ||||
|     this.#initAmount(); | ||||
|     this.#initItems(); | ||||
|     this.#initEvent(); | ||||
|   } | ||||
|  | ||||
|   #open() { | ||||
|     this.#list.classList.toggle('open'); | ||||
|     this.#caret.classList.toggle('caret_rotate'); | ||||
|   } | ||||
|  | ||||
|   #init(options) { | ||||
|     this.#options = options; | ||||
|     const elem = document.querySelector(options.selector); | ||||
|  | ||||
|     if (!elem) { | ||||
|       throw new Error(`Element with selector ${options.selector}`); | ||||
|     } | ||||
|  | ||||
|     this.#element = elem; | ||||
|   } | ||||
|  | ||||
|   #initSelected() { | ||||
|     const { styles } = this.#options; | ||||
|     if (this.#options.selected) { | ||||
|       this.#createSelected(this.#options.selected); | ||||
|     } else { | ||||
|       this.#createSelected('Select...'); | ||||
|     } | ||||
|  | ||||
|     if (!this.#options.selected && this.#options.placeholder) { | ||||
|       this.#createSelected(this.#options.placeholder); | ||||
|     } | ||||
|  | ||||
|     if ((styles && this.#options.placeholder) || (styles && this.#options.selected)) { | ||||
|       this.#createSelected(this.#options.placeholder); | ||||
|       this.#customStyles(styles); | ||||
|     } else { | ||||
|       this.#createSelected('Select...'); | ||||
|       this.#customStyles(styles); | ||||
|     } | ||||
|  | ||||
|     this.#element.addEventListener('click', () => { | ||||
|       this.#open(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   #initAmount() { | ||||
|     const { amount } = this.#options; | ||||
|  | ||||
|     if (!amount) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     let templete = ''; | ||||
|  | ||||
|     for (let i = 0; i < amount; i++) { | ||||
|       templete += `<li class="list__item">${i + 1}</li>`; | ||||
|     } | ||||
|     this.#element.innerHTML += `<ul class="list">${templete}</ul>`; | ||||
|   } | ||||
|  | ||||
|   #initItems() { | ||||
|     const { items, styles } = this.#options; | ||||
|  | ||||
|     if (!Array.isArray(items)) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     const templete = items.map((item) => `<li class="list__item" >${item}</li>`).join(''); | ||||
|     this.#element.innerHTML += `<ul class="list">${templete}</ul>`; | ||||
|  | ||||
|     if (styles) { | ||||
|       const templete = items.map((item) => `<li class="list__item" >${item}</li>`).join(''); | ||||
|       this.#element.innerHTML += `<ul class="list style = "${styles}">${templete}</ul>`; | ||||
|       this.#customStyles(styles); | ||||
|     } | ||||
|  | ||||
|     const options = this.#element.querySelectorAll('.list__item'); | ||||
|     const selected = this.#element.querySelector('.selected'); | ||||
|  | ||||
|     options.forEach((option) => { | ||||
|       option.addEventListener('click', () => { | ||||
|         selected.innerText = option.innerText; | ||||
|  | ||||
|         options.forEach((option) => { | ||||
|           option.classList.remove('active'); | ||||
|         }); | ||||
|         option.classList.add('active'); | ||||
|       }); | ||||
|     }); | ||||
|  | ||||
|     //ToDo: finish this function(catigories) | ||||
|     items.forEach((item) => { | ||||
|       if (typeof item === 'object') { | ||||
|         for (const key in item) { | ||||
|           const element = item[key]; | ||||
|           // console.log(element); | ||||
|           if (typeof element === 'string') { | ||||
|             console.log(element); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   #initEvent() { | ||||
|     const { event } = this.#options; | ||||
|  | ||||
|     this.#list = this.#element.querySelector('.list'); | ||||
|     this.#caret = this.#element.querySelector('.caret'); | ||||
|  | ||||
|     if (event === 'mouseenter') { | ||||
|       this.#element.addEventListener(event, () => { | ||||
|         this.#list.classList.add('open'); | ||||
|         this.#caret.classList.add('caret_rotate'); | ||||
|       }); | ||||
|  | ||||
|       this.#element.addEventListener('mouseleave', () => { | ||||
|         this.#list.classList.remove('open'); | ||||
|         this.#caret.classList.remove('caret_rotate'); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #customStyles(styles) { | ||||
|     if (!styles) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     const { head, caret, list, placeholder } = styles; | ||||
|     const select = this.#element.querySelector('.cg-select'); | ||||
|     const crt = this.#element.querySelector('.caret'); | ||||
|     const ul = this.#element.querySelector('.list'); | ||||
|     const placeh = this.#element.querySelector('.selected'); | ||||
|  | ||||
|     if (head) { | ||||
|       Object.entries(head).forEach(([key, value]) => { | ||||
|         select.style[key] = value; | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     if (caret) { | ||||
|       Object.entries(caret).forEach(([key, value]) => { | ||||
|         crt.style[key] = value; | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     if (ul) { | ||||
|       if (list) { | ||||
|         Object.entries(list).forEach(([key, value]) => { | ||||
|           ul.style[key] = value; | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (placeh) { | ||||
|       if (placeholder) { | ||||
|         Object.entries(placeholder).forEach(([key, value]) => { | ||||
|           placeh.style[key] = value; | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #createSelected(content, styles) { | ||||
|     this.#element.innerHTML = ` | ||||
|             <div class="cg-select"> | ||||
|                 <span class="selected">${content}</span> | ||||
|                 <div class="caret"></div> | ||||
|             </div> | ||||
|     `; | ||||
|  | ||||
|     if (styles) { | ||||
|       this.#customStyles(styles); | ||||
|  | ||||
|       this.#element.innerHTML = ` | ||||
|             <div class="cg-select" style = "${styles}"> | ||||
|                 <span class="selected" style = "${styles}">${content}</span> | ||||
|                 <div class="caret" style = "${styles}"></div> | ||||
|             </div> | ||||
|     `; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // addItem(item) { | ||||
|   //   const { items } = this.#options; | ||||
|  | ||||
|   //   console.log('Добавление елемента', item); | ||||
|  | ||||
|   //   items.push(item); | ||||
|  | ||||
|   //   console.log(items); | ||||
|   // } | ||||
| } | ||||
| @@ -4,26 +4,18 @@ | ||||
|     <meta charset="UTF-8" /> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Dropdown-list</title> | ||||
|     <link href="main.css" rel="stylesheet" /> | ||||
|     <title>Cg-Select</title> | ||||
|     <link href="./style/main.scss" rel="stylesheet" /> | ||||
|     <link rel="stylesheet" href="style/customStyle.scss" /> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div class="container"> | ||||
|       <div class="dropdown"> | ||||
|         <div class="select"> | ||||
|           <span class="selected">BMW</span> | ||||
|           <div class="caret"></div> | ||||
|         </div> | ||||
|       <div class="cg-dropdown"></div> | ||||
|  | ||||
|         <ul class="list"> | ||||
|           <li class="list__item">Nissan</li> | ||||
|           <li class="list__item">Mersedes</li> | ||||
|           <li class="list__item">Ford</li> | ||||
|           <li class="list__item active">Opel</li> | ||||
|           <li class="list__item">Chevrolet</li> | ||||
|         </ul> | ||||
|       </div> | ||||
|       <div class="cg-dropdown2"></div> | ||||
|  | ||||
|       <!-- <div class="cg-dropdown3"></div> --> | ||||
|     </div> | ||||
|   </body> | ||||
|   <script src="index.js"></script> | ||||
|   <script type="module" src="index.js"></script> | ||||
| </html> | ||||
|   | ||||
							
								
								
									
										69
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								src/index.js
									
									
									
									
									
								
							| @@ -1,27 +1,48 @@ | ||||
| const dropdowns = document.querySelectorAll('.dropdown'); | ||||
| import { DropDown } from './cg-dropdown'; | ||||
|  | ||||
| dropdowns.forEach(drop => { | ||||
|     const select = drop.querySelector('.select'); | ||||
|     const caret = drop.querySelector('.caret'); | ||||
|     const list = drop.querySelector('.list'); | ||||
|     const options = drop.querySelectorAll('.list__item') | ||||
|     const selected = drop.querySelector('.selected') | ||||
| const dropdown = new DropDown({ | ||||
|   selector: '.cg-dropdown', | ||||
|  | ||||
|     select.addEventListener('click', () => { | ||||
|         caret.classList.toggle('caret-rotate'); | ||||
|         list.classList.toggle('open'); | ||||
|     }); | ||||
|   items: ['BMW', 'Opel', 'Mersedes', 'MAN', 'max'], | ||||
| }); | ||||
|  | ||||
|     options.forEach(option => { | ||||
|         option.addEventListener('click', () =>{ | ||||
|             selected.innerText = option.innerText; | ||||
|             caret.classList.remove('caret-rotate');  | ||||
|             list.classList.remove('open'); | ||||
|              | ||||
|             options.forEach(option =>{ | ||||
|                 option.classList.remove('active'); | ||||
|             }) | ||||
|             option.classList.add('active'); | ||||
|         }) | ||||
|     }) | ||||
| })  | ||||
| const dropdown2 = new DropDown({ | ||||
|   selector: '.cg-dropdown2', | ||||
|   placeholder: 'Выберите авто', | ||||
|   items: ['BMW', 'Opel', 'Mersedes', 'MAN', 'Kamaz'], | ||||
|   event: 'mouseenter', | ||||
|   styles: { | ||||
|     head: { | ||||
|       background: 'red', | ||||
|       color: 'black', | ||||
|       width: '400px', | ||||
|     }, | ||||
|     placeholder: { | ||||
|       color: 'grey', | ||||
|     }, | ||||
|     caret: { | ||||
|       'border-top': '6px solid black', | ||||
|     }, | ||||
|     list: { | ||||
|       background: 'red', | ||||
|       color: 'black', | ||||
|       width: '412px', | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
|  | ||||
| // dropdown.addItem('Zaz'); | ||||
| // const dropdown3 = new DropDown({ | ||||
| //   selector: '.cg-dropdown3', | ||||
| //   selected: '', | ||||
| //   items: [ | ||||
| //     { | ||||
| //       title: 'Russia', | ||||
| //       item: ['Rostov', 'Moskow'], | ||||
| //     }, | ||||
| //     { | ||||
| //       title: 'Germany', | ||||
| //       item: ['Germany', 'Berlin'], | ||||
| //     }, | ||||
| //   ], | ||||
| // }); | ||||
|   | ||||
| @@ -1,26 +1,26 @@ | ||||
| * { | ||||
|   font-size: 14px; | ||||
|   font-family: Arial, Helvetica, sans-serif; | ||||
|    | ||||
| } | ||||
| body{ | ||||
| 
 | ||||
| body { | ||||
|   background: #1b1e25; | ||||
| } | ||||
| 
 | ||||
| .container { | ||||
|   display: flex; | ||||
|   margin: 50px auto; | ||||
|   width: 800px; | ||||
|   height: 200px; | ||||
| } | ||||
| 
 | ||||
| .dropdown { | ||||
|    | ||||
| .cg-dropdown { | ||||
|   position: relative; | ||||
|   margin-right: 10px; | ||||
| } | ||||
| 
 | ||||
| .select { | ||||
| .cg-select { | ||||
|   padding: 14px; | ||||
|   max-width: 200px; | ||||
|   min-width: 200px; | ||||
|   height: 30px; | ||||
|   color: #fff; | ||||
|   display: flex; | ||||
| @@ -31,11 +31,11 @@ body{ | ||||
|   cursor: pointer; | ||||
|   border-radius: 5px; | ||||
|   transition: 0.5s; | ||||
| } | ||||
| 
 | ||||
| .select:hover { | ||||
| transition: 0.5s; | ||||
|   background: #394050; | ||||
|   &:hover { | ||||
|     transition: 0.5s; | ||||
|     background: #394050; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .caret { | ||||
| @@ -45,18 +45,20 @@ transition: 0.5s; | ||||
|   border-right: 5px solid transparent; | ||||
|   border-top: 6px solid #fff; | ||||
|   transition: 0.5s; | ||||
| } | ||||
| 
 | ||||
| .caret-rotate { | ||||
|   transform: rotate(180deg); | ||||
|   transition: 0.5s; | ||||
|   &_rotate { | ||||
|     transform: rotate(180deg); | ||||
|     transition: 0.5s; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .list { | ||||
|   max-height: 230px; | ||||
|   overflow-y: auto; | ||||
|   position: absolute; | ||||
|   width: 212px; | ||||
|   padding: 7px; | ||||
|   margin-top: 1px; | ||||
|   margin-top: -0.2px; | ||||
|   list-style: none; | ||||
| 
 | ||||
|   color: white; | ||||
| @@ -69,24 +71,24 @@ transition: 0.5s; | ||||
|   opacity: 0; | ||||
|   display: none; | ||||
|   z-index: 1; | ||||
| } | ||||
| 
 | ||||
| .list__item { | ||||
|   &__item { | ||||
|     transition: 0.5s; | ||||
|   padding: 15px; | ||||
| } | ||||
|     padding: 15px; | ||||
| 
 | ||||
| .list__item:hover { | ||||
|     transition: 0.5s; | ||||
|   cursor: pointer; | ||||
|   background: #394050; | ||||
|     &:hover { | ||||
|       transition: 0.5s; | ||||
|       cursor: pointer; | ||||
|       background: #8282822c; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .active { | ||||
|   background: #394050; | ||||
|   background: #8282822c; | ||||
| } | ||||
| .open { | ||||
| 
 | ||||
| .open { | ||||
|   transition: 0.5s; | ||||
|   display: block; | ||||
|   opacity: 1; | ||||
		Reference in New Issue
	
	Block a user
	 MaxOvs19
					MaxOvs19