| @@ -127,6 +127,7 @@ | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -137,6 +137,7 @@ | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -24,15 +24,22 @@ | ||||
|             customStyles, | ||||
|             getFormatItem, | ||||
|             customStylesFormat, | ||||
| } from './components/utils'; | ||||
| import { createBreadcrumb } from './components/create-element'; | ||||
|             nativOptionMultiple, | ||||
|             nativOptionOrdinary, | ||||
|           } from './components/utils'; | ||||
|           import { | ||||
|             createBreadcrumb, | ||||
|             createInputSearch, | ||||
|             createNativSelectOption, | ||||
|             createNativeSelect, | ||||
|           } from './components/create-element'; | ||||
|            | ||||
| /** | ||||
|           /** | ||||
|            * @class Описание класса DropDown | ||||
|            * @description Этот класс реализовывает функционал кастомного селекта, с возможностями кастомизации. | ||||
|            *@author Овсяников Максим | ||||
|            */ | ||||
| export class DropDown { | ||||
|           export class DropDown { | ||||
|             /** | ||||
|              * Созданный HTML елемент | ||||
|              * @type {HTMLElement} | ||||
| @@ -353,7 +360,8 @@ export class DropDown { | ||||
|              * @description Рендер елементов в селекте. | ||||
|              */ | ||||
|             #render(select) { | ||||
|     const { styles, multiselect } = this.#options; | ||||
|               const { styles, multiselect, searchMode } = this.#options; | ||||
|               const random = Math.random().toString(36).substring(2, 10); | ||||
|            | ||||
|               if (select || (select && styles)) { | ||||
|                 this.#initSelected(select); | ||||
| @@ -363,8 +371,15 @@ export class DropDown { | ||||
|               } | ||||
|            | ||||
|               const ulList = document.createElement('ul'); | ||||
|               const intputSearch = createInputSearch(random); | ||||
|               this.random = random; | ||||
|            | ||||
|               const nativSelect = createNativeSelect(); | ||||
|            | ||||
|               ulList.classList.add('list'); | ||||
|               if (searchMode) { | ||||
|                 ulList.appendChild(intputSearch); | ||||
|               } | ||||
|            | ||||
|               if (styles) { | ||||
|                 const { list } = styles; | ||||
| @@ -374,7 +389,10 @@ export class DropDown { | ||||
|               this.#element.appendChild(ulList); | ||||
|            | ||||
|               this.#items.forEach((dataItem) => { | ||||
|                 this.#element.appendChild(nativSelect); | ||||
|            | ||||
|                 const liItem = document.createElement('li'); | ||||
|                 const nativOption = createNativSelectOption(); | ||||
|                 const strongItem = document.createElement('strong'); | ||||
|            | ||||
|                 liItem.classList.add('list__item'); | ||||
| @@ -386,12 +404,17 @@ export class DropDown { | ||||
|                   checkBox.setAttribute('id', `chbox-${dataItem.id}`); | ||||
|            | ||||
|                   liItem.appendChild(checkBox); | ||||
|                   nativSelect.setAttribute('multiple', 'multiple'); | ||||
|                 } | ||||
|            | ||||
|                 let textNode = ''; | ||||
|            | ||||
|                 if (dataItem.title) { | ||||
|                   nativOption.text = dataItem.title; | ||||
|                   nativOption.value = dataItem.title; | ||||
|                   textNode = document.createTextNode(dataItem.title); | ||||
|            | ||||
|                   nativSelect.appendChild(nativOption); | ||||
|                   liItem.appendChild(textNode); | ||||
|                   ulList.appendChild(liItem); | ||||
|                 } else { | ||||
| @@ -431,6 +454,8 @@ export class DropDown { | ||||
|               const response = await fetch(url); | ||||
|               const dataUrl = await response.json(); | ||||
|            | ||||
|               const nativSelect = createNativeSelect(); | ||||
|            | ||||
|               dataUrl.forEach((dataItem, index) => { | ||||
|                 const item = { | ||||
|                   id: dataItem.id, | ||||
| @@ -438,6 +463,8 @@ export class DropDown { | ||||
|                   value: index, | ||||
|                 }; | ||||
|                 const ulUrl = this.#element.querySelector('.list'); | ||||
|            | ||||
|                 const nativOption = createNativSelectOption(); | ||||
|                 const liUrl = document.createElement('li'); | ||||
|                 const textUrl = document.createTextNode(item.title); | ||||
|            | ||||
| @@ -446,17 +473,24 @@ export class DropDown { | ||||
|                   checkBox.type = 'checkbox'; | ||||
|            | ||||
|                   checkBox.setAttribute('id', `chbox-${item.id}`); | ||||
|                   nativSelect.setAttribute('multiple', 'multiple'); | ||||
|            | ||||
|                   liUrl.appendChild(checkBox); | ||||
|                 } | ||||
|            | ||||
|                 liUrl.classList.add('list__item'); | ||||
|                 nativOption.value = item.title; | ||||
|                 nativOption.text = item.title; | ||||
|            | ||||
|                 nativSelect.appendChild(nativOption); | ||||
|                 liUrl.appendChild(textUrl); | ||||
|                 ulUrl.appendChild(liUrl); | ||||
|            | ||||
|                 this.#items.push(item); | ||||
|               }); | ||||
|            | ||||
|               this.#element.appendChild(nativSelect); | ||||
|            | ||||
|               this.#items.filter((item, index) => { | ||||
|                 if (typeof item !== 'object') { | ||||
|                   this.#items.splice(index, 1); | ||||
| @@ -505,21 +539,26 @@ export class DropDown { | ||||
|              * @method #addOptionsBehaviour | ||||
|              */ | ||||
|             #addOptionsBehaviour() { | ||||
|     const { multiselect, placeholder, selected, multiselectTag } = this.#options; | ||||
|               const { multiselect, placeholder, selected, multiselectTag, searchMode } = this.#options; | ||||
|            | ||||
|               const options = this.#element.querySelectorAll('.list__item'); | ||||
|               const select = this.#element.querySelector('.selected'); | ||||
|  | ||||
|     const ul = document.createElement('ul'); | ||||
|               const nativOption = this.#element.querySelectorAll('.nativSelect__nativOption'); | ||||
|               const ulMultipul = document.createElement('ul'); | ||||
|            | ||||
|               if (multiselect) { | ||||
|       ul.classList.add('multiselect-tag'); | ||||
|                 ulMultipul.classList.add('multiselect-tag'); | ||||
|                 select.classList.add('overflow-hidden'); | ||||
|               } | ||||
|            | ||||
|               if (searchMode && searchMode === true) { | ||||
|                 this.#searchMode(this.random); | ||||
|               } | ||||
|            | ||||
|               options.forEach((option, index) => { | ||||
|                 option.addEventListener('click', (event) => { | ||||
|                   const item = this.#items[index]; | ||||
|            | ||||
|                   if (multiselect) { | ||||
|                     event.stopPropagation(); | ||||
|                     option.classList.toggle('active'); | ||||
| @@ -534,13 +573,15 @@ export class DropDown { | ||||
|                       const checkIndex = this.#indexes.indexOf(index); | ||||
|            | ||||
|                       if (checkIndex === -1) { | ||||
|                         nativOptionMultiple(nativOption, item.title, true); | ||||
|            | ||||
|                         this.#indexes.push(index); | ||||
|            | ||||
|                         select.innerText = ''; | ||||
|            | ||||
|                         if (multiselectTag) { | ||||
|                           this.#selectedItems.push(item); | ||||
|                 select.appendChild(ul); | ||||
|                           select.appendChild(ulMultipul); | ||||
|            | ||||
|                           const data = { | ||||
|                             option: this.#options, | ||||
| @@ -549,7 +590,7 @@ export class DropDown { | ||||
|                             selectedItems: this.#selectedItems, | ||||
|                           }; | ||||
|            | ||||
|                 ul.appendChild(createBreadcrumb(data, item.title, index, item.id)); | ||||
|                           ulMultipul.appendChild(createBreadcrumb(data, item.title, index, item.id)); | ||||
|                         } else { | ||||
|                           this.#selectedItems.push(item.title); | ||||
|                           select.innerText = this.#selectedItems; | ||||
| @@ -557,11 +598,11 @@ export class DropDown { | ||||
|                       } else { | ||||
|                         if (multiselectTag) { | ||||
|                           const tagItem = document.getElementById(`tag-${index}-${item.id}`); | ||||
|  | ||||
|                 ul.removeChild(tagItem); | ||||
|                           ulMultipul.removeChild(tagItem); | ||||
|                         } | ||||
|                         this.#indexes.splice(checkIndex, 1); | ||||
|                         this.#selectedItems.splice(checkIndex, 1); | ||||
|                         nativOptionMultiple(nativOption, item.title, false); | ||||
|                       } | ||||
|            | ||||
|                       if (!this.#selectedItems.length) { | ||||
| @@ -574,7 +615,7 @@ export class DropDown { | ||||
|                         } | ||||
|                       } else { | ||||
|                         if (multiselectTag) { | ||||
|                 select.appendChild(ul); | ||||
|                           select.appendChild(ulMultipul); | ||||
|                         } else { | ||||
|                           select.innerText = this.#selectedItems; | ||||
|                         } | ||||
| @@ -583,6 +624,7 @@ export class DropDown { | ||||
|                   } else { | ||||
|                     select.innerText = item.title; | ||||
|                     this.#selectedItems = item; | ||||
|                     nativOptionOrdinary(nativOption, item.title); | ||||
|            | ||||
|                     options.forEach((option) => { | ||||
|                       option.classList.remove('active'); | ||||
| @@ -593,6 +635,47 @@ export class DropDown { | ||||
|               }); | ||||
|             } | ||||
|            | ||||
|             /** | ||||
|              * Метод который реализует поиск элементов в селекте | ||||
|              * @protected | ||||
|              * @param {string} random уникальное значение для input элемента. | ||||
|              * @method #searchMode | ||||
|              */ | ||||
|             #searchMode(random) { | ||||
|               const input = this.#element.querySelector(`#searchSelect-${random}`); | ||||
|               const searchSelect = this.#element.querySelectorAll('.list__item'); | ||||
|               const result = document.createElement('p'); | ||||
|               const textNode = document.createTextNode('No matches...'); | ||||
|            | ||||
|               result.appendChild(textNode); | ||||
|               result.classList.add('displayHide'); | ||||
|               input.parentElement.appendChild(result); | ||||
|            | ||||
|               input.addEventListener('click', (e) => { | ||||
|                 e.stopPropagation(); | ||||
|               }); | ||||
|            | ||||
|               input.oninput = function () { | ||||
|                 let val = this.value.trim(); | ||||
|            | ||||
|                 if (val != '') { | ||||
|                   searchSelect.forEach((elem) => { | ||||
|                     if (elem.innerText.search(val) == -1) { | ||||
|                       elem.classList.add('displayHide'); | ||||
|                       result.classList.remove('displayHide'); | ||||
|                     } else { | ||||
|                       elem.classList.remove('displayHide'); | ||||
|                     } | ||||
|                   }); | ||||
|                 } else { | ||||
|                   searchSelect.forEach((elem) => { | ||||
|                     elem.classList.remove('displayHide'); | ||||
|                     result.classList.add('displayHide'); | ||||
|                   }); | ||||
|                 } | ||||
|               }; | ||||
|             } | ||||
|            | ||||
|             /** | ||||
|              * Приватный метод экземпляра класса DropDown | ||||
|              * @protected | ||||
| @@ -616,7 +699,7 @@ export class DropDown { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
| } | ||||
|           } | ||||
| </code></pre> | ||||
|         </article> | ||||
|       </section> | ||||
| @@ -649,6 +732,7 @@ export class DropDown { | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -21,12 +21,12 @@ | ||||
|         <article> | ||||
|           <pre | ||||
|             class="prettyprint source linenums" | ||||
|           ><code>import { customStylesFormat } from './utils'; | ||||
| /** | ||||
|  * @module createElementChips | ||||
|           ><code>import { customStylesFormat, nativOptionMultiple } from './utils'; | ||||
|             /** | ||||
|              * @module createBreadcrumb | ||||
|              */ | ||||
|              | ||||
| /** | ||||
|             /** | ||||
|              * Метод который создает и отвечает за поведение chips | ||||
|              * @param {object} data объект в котором содержатся настройки и элементы селекта | ||||
|              * @param {string} title имя выбранного элемента для отрисовки chips | ||||
| @@ -34,11 +34,13 @@ | ||||
|              * @param {string} id уникальное id выбранного элемента | ||||
|              * @returns {HTMLElement} возвращает сформированный HTMLElement chips item | ||||
|              */ | ||||
| export function createBreadcrumb(data, title, index, id) { | ||||
|             export function createBreadcrumb(data, title, index, id) { | ||||
|               const { element, option, indexes, selectedItems } = data; | ||||
|               const { placeholder, styles } = option; | ||||
|              | ||||
|               const selected = element.querySelector('.selected'); | ||||
|               const nativOption = element.querySelectorAll('.nativSelect__nativOption'); | ||||
|              | ||||
|               const liChip = document.createElement('li'); | ||||
|               const textNode = document.createTextNode(title); | ||||
|               const svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | ||||
| @@ -64,14 +66,14 @@ export function createBreadcrumb(data, title, index, id) { | ||||
|              | ||||
|               svgIcon.addEventListener('click', (event) => { | ||||
|                 event.stopPropagation(); | ||||
|                 nativOptionMultiple(nativOption, title, false); | ||||
|              | ||||
|                 const deleteIcon = indexes.indexOf(index); | ||||
|                 let checkBox = ''; | ||||
|              | ||||
|                 indexes.splice(deleteIcon, 1); | ||||
|                 selectedItems.splice(deleteIcon, 1); | ||||
|              | ||||
|     let checkBox = ''; | ||||
|  | ||||
|                 if (id) { | ||||
|                   checkBox = document.getElementById(`chbox-${id}`); | ||||
|                 } else { | ||||
| @@ -89,7 +91,47 @@ export function createBreadcrumb(data, title, index, id) { | ||||
|               }); | ||||
|              | ||||
|               return liChip; | ||||
| } | ||||
|             } | ||||
|              | ||||
|             /** | ||||
|              * Метод который создает нативный селект | ||||
|              * @returns {HTMLSelectElement} Возвращает созданный нативный селект | ||||
|              */ | ||||
|             export function createNativeSelect() { | ||||
|               const nativSelect = document.createElement('select'); | ||||
|              | ||||
|               nativSelect.setAttribute('form', 'data'); | ||||
|               nativSelect.setAttribute('name', 'dataSelect'); | ||||
|               nativSelect.classList.add('nativSelect'); | ||||
|               return nativSelect; | ||||
|             } | ||||
|              | ||||
|             /** | ||||
|              * Метод который создает Options для нативного селекта | ||||
|              * @returns {HTMLOptionElement} Возвращает созданные Options нативного селекта | ||||
|              */ | ||||
|             export function createNativSelectOption() { | ||||
|               const nativOption = document.createElement('option'); | ||||
|              | ||||
|               nativOption.classList.add('nativSelect__nativOption'); | ||||
|               return nativOption; | ||||
|             } | ||||
|              | ||||
|             /** | ||||
|              * Метод который создает поиск элементов в селекте | ||||
|              * @param {string} random уникальное значение для input элемента. | ||||
|              * @returns {HTMLInputElement} Возвращает сформированный input елемент. | ||||
|              */ | ||||
|             export function createInputSearch(random) { | ||||
|               const intputSearch = document.createElement('input'); | ||||
|              | ||||
|               intputSearch.type = 'text'; | ||||
|               intputSearch.classList.add('inputSearch'); | ||||
|               intputSearch.setAttribute('id', `searchSelect-${random}`); | ||||
|               intputSearch.setAttribute('placeholder', 'Search...'); | ||||
|              | ||||
|               return intputSearch; | ||||
|             } | ||||
| </code></pre> | ||||
|         </article> | ||||
|       </section> | ||||
| @@ -122,6 +164,7 @@ export function createBreadcrumb(data, title, index, id) { | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -301,6 +301,52 @@ | ||||
|             </dd> | ||||
|           </dl> | ||||
|  | ||||
|           <h4 class="name" id="searchMode"> | ||||
|             <span class="type-signature">(protected) </span>#searchMode<span class="signature" | ||||
|               >(random)</span | ||||
|             ><span class="type-signature"></span> | ||||
|           </h4> | ||||
|  | ||||
|           <div class="description">Метод который реализует поиск элементов в селекте</div> | ||||
|  | ||||
|           <h5>Parameters:</h5> | ||||
|  | ||||
|           <table class="params"> | ||||
|             <thead> | ||||
|               <tr> | ||||
|                 <th>Name</th> | ||||
|  | ||||
|                 <th>Type</th> | ||||
|  | ||||
|                 <th class="last">Description</th> | ||||
|               </tr> | ||||
|             </thead> | ||||
|  | ||||
|             <tbody> | ||||
|               <tr> | ||||
|                 <td class="name"><code>random</code></td> | ||||
|  | ||||
|                 <td class="type"> | ||||
|                   <span class="param-type">string</span> | ||||
|                 </td> | ||||
|  | ||||
|                 <td class="description last">уникальное значение для input элемента.</td> | ||||
|               </tr> | ||||
|             </tbody> | ||||
|           </table> | ||||
|  | ||||
|           <dl class="details"> | ||||
|             <dt class="tag-source">Source:</dt> | ||||
|             <dd class="tag-source"> | ||||
|               <ul class="dummy"> | ||||
|                 <li> | ||||
|                   <a href="cg-dropdown.js.html">cg-dropdown.js</a>, | ||||
|                   <a href="cg-dropdown.js.html#line617">line 617</a> | ||||
|                 </li> | ||||
|               </ul> | ||||
|             </dd> | ||||
|           </dl> | ||||
|  | ||||
|           <h4 class="name" id="addItem"> | ||||
|             <span class="type-signature"></span>addItem<span class="signature">(item)</span | ||||
|             ><span class="type-signature"></span> | ||||
| @@ -657,6 +703,7 @@ | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -47,6 +47,7 @@ | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -379,6 +379,7 @@ | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|   | ||||
| @@ -114,6 +114,63 @@ | ||||
|             </dd> | ||||
|           </dl> | ||||
|  | ||||
|           <h4 class="name" id=".createInputSearch"> | ||||
|             <span class="type-signature">(static) </span>createInputSearch<span class="signature" | ||||
|               >(random)</span | ||||
|             ><span class="type-signature"> → {HTMLInputElement}</span> | ||||
|           </h4> | ||||
|  | ||||
|           <div class="description">Метод который создает поиск элементов в селекте</div> | ||||
|  | ||||
|           <h5>Parameters:</h5> | ||||
|  | ||||
|           <table class="params"> | ||||
|             <thead> | ||||
|               <tr> | ||||
|                 <th>Name</th> | ||||
|  | ||||
|                 <th>Type</th> | ||||
|  | ||||
|                 <th class="last">Description</th> | ||||
|               </tr> | ||||
|             </thead> | ||||
|  | ||||
|             <tbody> | ||||
|               <tr> | ||||
|                 <td class="name"><code>random</code></td> | ||||
|  | ||||
|                 <td class="type"> | ||||
|                   <span class="param-type">string</span> | ||||
|                 </td> | ||||
|  | ||||
|                 <td class="description last">уникальное значение для input элемента.</td> | ||||
|               </tr> | ||||
|             </tbody> | ||||
|           </table> | ||||
|  | ||||
|           <dl class="details"> | ||||
|             <dt class="tag-source">Source:</dt> | ||||
|             <dd class="tag-source"> | ||||
|               <ul class="dummy"> | ||||
|                 <li> | ||||
|                   <a href="create-element.js.html">create-element.js</a>, | ||||
|                   <a href="create-element.js.html#line102">line 102</a> | ||||
|                 </li> | ||||
|               </ul> | ||||
|             </dd> | ||||
|           </dl> | ||||
|  | ||||
|           <h5>Returns:</h5> | ||||
|  | ||||
|           <div class="param-desc">Возвращает сформированный input елемент.</div> | ||||
|  | ||||
|           <dl> | ||||
|             <dt>Type</dt> | ||||
|             <dd> | ||||
|               <span class="param-type">HTMLInputElement</span> | ||||
|             </dd> | ||||
|           </dl> | ||||
|  | ||||
|           <h4 class="name" id=".createNativeSelect"> | ||||
|             <span class="type-signature">(static) </span>createNativeSelect<span class="signature" | ||||
|               >()</span | ||||
| @@ -192,21 +249,25 @@ | ||||
|           > | ||||
|         </li> | ||||
|       </ul> | ||||
|       <h3>Module</h3> | ||||
|       <h3>Modules</h3> | ||||
|       <ul> | ||||
|         <li><a href="module-Utils.html">Utils</a></li> | ||||
|         <li><a href="module-createElementChips.html">createElementChips</a></li> | ||||
|       </ul> | ||||
|       <h3>Global</h3> | ||||
|       <h3>Private methods</h3> | ||||
|       <ul> | ||||
|         <li><a href="global.html#addOptionsBehaviour">#addOptionsBehaviour</a></li> | ||||
|         <li><a href="global.html#close">#close</a></li> | ||||
|         <li><a href="global.html#init">#init</a></li> | ||||
|         <li><a href="global.html#initEvent">#initEvent</a></li> | ||||
|         <li><a href="global.html#initSelected">#initSelected</a></li> | ||||
|         <li><a href="global.html#open">#open</a></li> | ||||
|         <li><a href="global.html#render">#render</a></li> | ||||
|         <li><a href="global.html#renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#searchMode">#searchMode</a></li> | ||||
|       </ul> | ||||
|       <h3>Public methods</h3> | ||||
|       <ul> | ||||
|         <li><a href="global.html##addOptionsBehaviour">#addOptionsBehaviour</a></li> | ||||
|         <li><a href="global.html##close">#close</a></li> | ||||
|         <li><a href="global.html##init">#init</a></li> | ||||
|         <li><a href="global.html##initEvent">#initEvent</a></li> | ||||
|         <li><a href="global.html##initSelected">#initSelected</a></li> | ||||
|         <li><a href="global.html##open">#open</a></li> | ||||
|         <li><a href="global.html##render">#render</a></li> | ||||
|         <li><a href="global.html##renderUrl">#renderUrl</a></li> | ||||
|         <li><a href="global.html#addItem">addItem</a></li> | ||||
|         <li><a href="global.html#buttonControl">buttonControl</a></li> | ||||
|         <li><a href="global.html#deleteItem">deleteItem</a></li> | ||||
|   | ||||
| @@ -21,16 +21,16 @@ | ||||
|         <article> | ||||
|           <pre class="prettyprint source linenums"><code>/** | ||||
|             * Utils module | ||||
|  * @module Utils; | ||||
|             * @module Utils | ||||
|             */ | ||||
|             | ||||
| /** | ||||
|            /** | ||||
|             * Создание кнопки выбора элементов | ||||
|             * @param {HTMLElement} element созданный экземпляр класса DropDown | ||||
|             * @param {string} content placeholer передаваемый из настроек селекта | ||||
|             * @param {object} styles не обязательный параметр. Объект в котором находяться настройки кастомизации частей селекта | ||||
|             */ | ||||
| export function createSelected(element, content, styles) { | ||||
|            export function createSelected(element, content, styles) { | ||||
|              if (content) { | ||||
|                element.innerHTML = ` | ||||
|                  <div class="cg-select"> | ||||
| @@ -50,14 +50,14 @@ export function createSelected(element, content, styles) { | ||||
|                  </div> | ||||
|                `; | ||||
|              } | ||||
| } | ||||
|            } | ||||
|             | ||||
| /** | ||||
|            /** | ||||
|             * Поиск и стилизация елементов полученных из styles экземпляра DropDown | ||||
|             * @param {HTMLElement} element созданный экземпляр класса DropDown | ||||
|             * @param {object} styles объект в котором находяться настройки кастомизации частей селекта | ||||
|             */ | ||||
| export function customStyles(element, styles) { | ||||
|            export function customStyles(element, styles) { | ||||
|              if (!styles) { | ||||
|                return; | ||||
|              } | ||||
| @@ -75,48 +75,41 @@ export function customStyles(element, styles) { | ||||
|              if (placeholderSelect) { | ||||
|                customStylesFormat(placeholder, placeholderSelect); | ||||
|              } | ||||
| } | ||||
|            } | ||||
|             | ||||
| // export function customStylesFormat(elemOption, selector) { | ||||
| //   if (elemOption) { | ||||
| //     Object.entries(elemOption).forEach(([key, value]) => { | ||||
| //       selector.style[key] = value; | ||||
| //     }); | ||||
| //   } | ||||
| // } | ||||
| /** | ||||
|            /** | ||||
|             * Универсальный метод для стилизации селекта | ||||
|             * @param {object} elemOption объект полученное из объекта styles у которого мы получаем ключ-значение стилей | ||||
|             * @param {HTMLElement} selector  HTMLElement подвергающиеся кастомизации | ||||
|             */ | ||||
| exports.customStylesFormat = (elemOption, selector) => { | ||||
|            export function customStylesFormat(elemOption, selector) { | ||||
|              if (elemOption) { | ||||
|                Object.entries(elemOption).forEach(([key, value]) => { | ||||
|                  selector.style[key] = value; | ||||
|                }); | ||||
|              } | ||||
| }; | ||||
|            } | ||||
|             | ||||
| /** | ||||
|            /** | ||||
|             * Проверка содержит ли item  указанные свойства, | ||||
|             * @param {object} item проверяемый на определенную структуру элемент | ||||
|             * @returns {boolean} возвращает true/false если item содержит указанные свойства | ||||
|             */ | ||||
| export function checkItemStruct(item) { | ||||
|            export function checkItemStruct(item) { | ||||
|              if (item && typeof item !== 'object') { | ||||
|                return false; | ||||
|              } | ||||
|             | ||||
|              return item.hasOwnProperty('id') && item.hasOwnProperty('title') && item.hasOwnProperty('value'); | ||||
| } | ||||
|            } | ||||
|             | ||||
| /** | ||||
|            /** | ||||
|             * Преобразование каждого елемента полученного из поля Items; | ||||
|             * @param {object | string} dataItem полученный елемент переданный при создании селекта может быть как object/string | ||||
|             * @param {number} index индекс этого элемента | ||||
|             * @returns {object} возвращает сформированный объект | ||||
|             */ | ||||
| export function getFormatItem(dataItem, index) { | ||||
|            export function getFormatItem(dataItem, index) { | ||||
|              const random = Math.random().toString(36).substring(2, 10); | ||||
|              let item = {}; | ||||
|             | ||||
| @@ -135,7 +128,43 @@ export function getFormatItem(dataItem, index) { | ||||
|              } | ||||
|             | ||||
|              return item; | ||||
| } | ||||
|            } | ||||
|             | ||||
|            /** | ||||
|             * Поведение нативного(одинарного) селекта при выборе кастомного | ||||
|             * @param {NodeList} element NodeList нативного селекта | ||||
|             * @param {object} item выбранный элемент в кастомном селекте | ||||
|             */ | ||||
|            export function nativOptionOrdinary(element, item) { | ||||
|              element.forEach((option) => { | ||||
|                option.removeAttribute('selected'); | ||||
|                if (option.textContent === item) { | ||||
|                  option.setAttribute('selected', 'selected'); | ||||
|                } | ||||
|              }); | ||||
|            } | ||||
|             | ||||
|            /** | ||||
|             * Поведение нативного(Multiple) селекта при выборе в кастомном | ||||
|             * @param {NodeList} element NodeList нативного селекта | ||||
|             * @param {object} item выбранный элемент в кастомном селекте | ||||
|             * @param {boolean} condition специальный флаг при котором добавляются/убераются атрибуты у нативного селекта | ||||
|             */ | ||||
|            export function nativOptionMultiple(element, item, condition) { | ||||
|              element.forEach((option) => { | ||||
|                if (condition == true) { | ||||
|                  if (option.textContent === item) { | ||||
|                    option.setAttribute('selected', 'selected'); | ||||
|                  } | ||||
|                } else if (condition == false) { | ||||
|                  if (option.textContent === item) { | ||||
|                    option.removeAttribute('selected'); | ||||
|                  } | ||||
|                } else { | ||||
|                  return; | ||||
|                } | ||||
|              }); | ||||
|            } | ||||
| </code></pre> | ||||
|         </article> | ||||
|       </section> | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import { | ||||
| } from './components/utils'; | ||||
| import { | ||||
|   createBreadcrumb, | ||||
|   createInputSearch, | ||||
|   createNativSelectOption, | ||||
|   createNativeSelect, | ||||
| } from './components/create-element'; | ||||
| @@ -338,7 +339,8 @@ export class DropDown { | ||||
|    * @description Рендер елементов в селекте. | ||||
|    */ | ||||
|   #render(select) { | ||||
|     const { styles, multiselect } = this.#options; | ||||
|     const { styles, multiselect, searchMode } = this.#options; | ||||
|     const random = Math.random().toString(36).substring(2, 10); | ||||
|  | ||||
|     if (select || (select && styles)) { | ||||
|       this.#initSelected(select); | ||||
| @@ -348,9 +350,15 @@ export class DropDown { | ||||
|     } | ||||
|  | ||||
|     const ulList = document.createElement('ul'); | ||||
|     const intputSearch = createInputSearch(random); | ||||
|     this.random = random; | ||||
|  | ||||
|     const nativSelect = createNativeSelect(); | ||||
|  | ||||
|     ulList.classList.add('list'); | ||||
|     if (searchMode) { | ||||
|       ulList.appendChild(intputSearch); | ||||
|     } | ||||
|  | ||||
|     if (styles) { | ||||
|       const { list } = styles; | ||||
| @@ -510,12 +518,11 @@ export class DropDown { | ||||
|    * @method #addOptionsBehaviour | ||||
|    */ | ||||
|   #addOptionsBehaviour() { | ||||
|     const { multiselect, placeholder, selected, multiselectTag } = this.#options; | ||||
|     const { multiselect, placeholder, selected, multiselectTag, searchMode } = this.#options; | ||||
|  | ||||
|     const options = this.#element.querySelectorAll('.list__item'); | ||||
|     const select = this.#element.querySelector('.selected'); | ||||
|     const nativOption = this.#element.querySelectorAll('.nativSelect__nativOption'); | ||||
|  | ||||
|     const ulMultipul = document.createElement('ul'); | ||||
|  | ||||
|     if (multiselect) { | ||||
| @@ -523,6 +530,10 @@ export class DropDown { | ||||
|       select.classList.add('overflow-hidden'); | ||||
|     } | ||||
|  | ||||
|     if (searchMode && searchMode === true) { | ||||
|       this.#searchMode(this.random); | ||||
|     } | ||||
|  | ||||
|     options.forEach((option, index) => { | ||||
|       option.addEventListener('click', (event) => { | ||||
|         const item = this.#items[index]; | ||||
| @@ -603,6 +614,47 @@ export class DropDown { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Метод который реализует поиск элементов в селекте | ||||
|    * @protected | ||||
|    * @param {string} random уникальное значение для input элемента. | ||||
|    * @method #searchMode | ||||
|    */ | ||||
|   #searchMode(random) { | ||||
|     const input = this.#element.querySelector(`#searchSelect-${random}`); | ||||
|     const searchSelect = this.#element.querySelectorAll('.list__item'); | ||||
|     const result = document.createElement('p'); | ||||
|     const textNode = document.createTextNode('No matches...'); | ||||
|  | ||||
|     result.appendChild(textNode); | ||||
|     result.classList.add('displayHide'); | ||||
|     input.parentElement.appendChild(result); | ||||
|  | ||||
|     input.addEventListener('click', (e) => { | ||||
|       e.stopPropagation(); | ||||
|     }); | ||||
|  | ||||
|     input.oninput = function () { | ||||
|       let val = this.value.trim(); | ||||
|  | ||||
|       if (val != '') { | ||||
|         searchSelect.forEach((elem) => { | ||||
|           if (elem.innerText.search(val) == -1) { | ||||
|             elem.classList.add('displayHide'); | ||||
|             result.classList.remove('displayHide'); | ||||
|           } else { | ||||
|             elem.classList.remove('displayHide'); | ||||
|           } | ||||
|         }); | ||||
|       } else { | ||||
|         searchSelect.forEach((elem) => { | ||||
|           elem.classList.remove('displayHide'); | ||||
|           result.classList.add('displayHide'); | ||||
|         }); | ||||
|       } | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Приватный метод экземпляра класса DropDown | ||||
|    * @protected | ||||
|   | ||||
| @@ -93,3 +93,19 @@ export function createNativSelectOption() { | ||||
|   nativOption.classList.add('nativSelect__nativOption'); | ||||
|   return nativOption; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Метод который создает поиск элементов в селекте | ||||
|  * @param {string} random уникальное значение для input элемента. | ||||
|  * @returns {HTMLInputElement} Возвращает сформированный input елемент. | ||||
|  */ | ||||
| export function createInputSearch(random) { | ||||
|   const intputSearch = document.createElement('input'); | ||||
|  | ||||
|   intputSearch.type = 'text'; | ||||
|   intputSearch.classList.add('inputSearch'); | ||||
|   intputSearch.setAttribute('id', `searchSelect-${random}`); | ||||
|   intputSearch.setAttribute('placeholder', 'Search...'); | ||||
|  | ||||
|   return intputSearch; | ||||
| } | ||||
|   | ||||
| @@ -10,13 +10,13 @@ | ||||
|   </head> | ||||
|   <body> | ||||
|     <div class="container"> | ||||
|       <form id="data" action="handler.php"></form> | ||||
|       <!-- <form id="data" action="handler.php"></form> --> | ||||
|  | ||||
|       <button class="cg-dropdown cg-dropdown_one"></button> | ||||
|       <input type="submit" form="data" value="Отправить" /> | ||||
|       <!-- <input type="submit" form="data" value="Отправить" /> --> | ||||
|       <button class="cg-dropdown cg-dropdown_three"></button> | ||||
|  | ||||
|       <!-- <button class="cg-dropdown cg-dropdown_button" style="margin-top: 50px"></button> --> | ||||
|       <button class="cg-dropdown cg-dropdown_button" style="margin-top: 50px"></button> | ||||
|     </div> | ||||
|   </body> | ||||
|   <script type="module" src="index.js"></script> | ||||
|   | ||||
							
								
								
									
										89
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								src/index.js
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import { DropDown } from './cg-dropdown'; | ||||
| const dropdown = new DropDown({ | ||||
|   selector: '.cg-dropdown_one', | ||||
|   placeholder: 'Выберите авто', | ||||
|   searchMode: true, | ||||
|   items: [ | ||||
|     'BMW', | ||||
|     { | ||||
| @@ -19,12 +20,13 @@ const dropdown = new DropDown({ | ||||
|   multiselectTag: true, | ||||
| }); | ||||
|  | ||||
| dropdown.disabled(false); | ||||
| // dropdown.disabled(false); | ||||
| // ------------------------------URL-------------------- | ||||
| const dropdown3 = new DropDown({ | ||||
|   selector: '.cg-dropdown_three', | ||||
|   placeholder: 'URL', | ||||
|   url: 'http://jsonplaceholder.typicode.com/users', | ||||
|   searchMode: true, | ||||
|   styles: { | ||||
|     head: { | ||||
|       background: 'black', | ||||
| @@ -36,48 +38,49 @@ const dropdown3 = new DropDown({ | ||||
| }); | ||||
|  | ||||
| // --------------------------------Категории-------------------------- | ||||
| // const dropdown4 = new DropDown({ | ||||
| //   selector: '.cg-dropdown_button', | ||||
| //   placeholder: 'Выберите регион', | ||||
| //   items: [ | ||||
| //     { | ||||
| //       category: 'Russia', | ||||
| //       categoryItems: [ | ||||
| //         { | ||||
| //           id: '28qwds', | ||||
| //           title: 'Москва', | ||||
| //           value: 0, | ||||
| //         }, | ||||
| //         , | ||||
| //         'Ростов-на-дону', | ||||
| //         'Саратов', | ||||
| //         'Волгоград', | ||||
| //         'Донецк', | ||||
| //       ], | ||||
| //     }, | ||||
| //     { | ||||
| //       category: 'USA', | ||||
| //       categoryItems: ['Alabama', 'Texas', 'Colorado', 'Klirens', 'Los-Angeles'], | ||||
| //     }, | ||||
| //     { | ||||
| //       category: 'France', | ||||
| //       categoryItems: ['Paris'], | ||||
| //     }, | ||||
| //   ], | ||||
| //   styles: { | ||||
| //     head: { | ||||
| //       background: 'red', | ||||
| //     }, | ||||
| //     list: { | ||||
| //       background: 'green', | ||||
| //     }, | ||||
| //     chips: { | ||||
| //       background: 'blue', | ||||
| //     }, | ||||
| //   }, | ||||
| //   multiselect: true, | ||||
| //   multiselectTag: true, | ||||
| // }); | ||||
| const dropdown4 = new DropDown({ | ||||
|   selector: '.cg-dropdown_button', | ||||
|   placeholder: 'Выберите регион', | ||||
|   searchMode: true, | ||||
|   items: [ | ||||
|     { | ||||
|       category: 'Russia', | ||||
|       categoryItems: [ | ||||
|         { | ||||
|           id: '28qwds', | ||||
|           title: 'Москва', | ||||
|           value: 0, | ||||
|         }, | ||||
|         , | ||||
|         'Ростов-на-дону', | ||||
|         'Саратов', | ||||
|         'Волгоград', | ||||
|         'Донецк', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       category: 'USA', | ||||
|       categoryItems: ['Alabama', 'Texas', 'Colorado', 'Klirens', 'Los-Angeles'], | ||||
|     }, | ||||
|     { | ||||
|       category: 'France', | ||||
|       categoryItems: ['Paris'], | ||||
|     }, | ||||
|   ], | ||||
|   styles: { | ||||
|     head: { | ||||
|       background: 'red', | ||||
|     }, | ||||
|     list: { | ||||
|       background: 'green', | ||||
|     }, | ||||
|     chips: { | ||||
|       background: 'blue', | ||||
|     }, | ||||
|   }, | ||||
|   multiselect: true, | ||||
|   multiselectTag: true, | ||||
| }); | ||||
|  | ||||
| //----------------управление с помощью кнопок---------------------------------- | ||||
| /* const buttonOpen = document.querySelector('.button__open'); | ||||
|   | ||||
| @@ -29,7 +29,7 @@ body { | ||||
|  | ||||
| .cg-select { | ||||
|   padding: 5px; | ||||
|  | ||||
|   flex-grow: 1; | ||||
|   min-height: 50px; | ||||
|   color: #fff; | ||||
|   display: flex; | ||||
| @@ -105,6 +105,18 @@ body { | ||||
|       background: #8282822c; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .inputSearch { | ||||
|     background: transparent; | ||||
|     border: none; | ||||
|     border-bottom: 1px solid white; | ||||
|     margin-top: 5px; | ||||
|     margin-bottom: 5px; | ||||
|  | ||||
|     &:focus { | ||||
|       outline: none; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .multiselect-tag { | ||||
| @@ -210,3 +222,7 @@ input[type='checkbox'] { | ||||
| ::-webkit-scrollbar-thumb { | ||||
|   background-color: #4d4d4d; | ||||
| } | ||||
|  | ||||
| .displayHide { | ||||
|   display: none; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 MaxOvs19
					MaxOvs19