treeselectjs 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -19
- package/dist/input.js +1 -1
- package/dist/list.js +1 -1
- package/dist/treeselect-js.js +1 -1
- package/package.json +1 -1
- package/src/input.js +3 -1
- package/src/list.js +3 -3
- package/src/treeselect-js.js +34 -16
package/README.md
CHANGED
|
@@ -98,33 +98,36 @@ slot.addEventListener('click', (e) => {
|
|
|
98
98
|
### Props
|
|
99
99
|
Name | Type (default) | Description
|
|
100
100
|
------------- | ------------- | -------------
|
|
101
|
-
parentHtmlContainer | HTMLElement (required!) | It should be a HTML element (div), it will be changed to the list container.
|
|
102
|
-
value | Array[String] ([]) |
|
|
103
|
-
options | Array[Object] ([]) | It is an array of objects { name: String, value: String, children: [] }
|
|
104
|
-
openLevel | Number (0) | All groups will be opened to this level.
|
|
105
|
-
appendToBody | Boolean (false) | List will be appended to the body instead of the input container.
|
|
106
|
-
alwaysOpen | Boolean (false) | List will be always opened. You can use it for comfortable style changing. If you what to use it as an opened list, turn `staticList
|
|
107
|
-
showTags | Boolean (true) | Selected values look like tags. The false value shows results as '{count} elements selected'.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
101
|
+
**parentHtmlContainer** | HTMLElement (required!) | It should be a HTML element (div), it will be changed to the list container.
|
|
102
|
+
**value** | Array[String] ([]) | An array of `value` from `options` prop. This value will be selected on load of the treeselect. You can call `updateValue` to update prop or set value `treeselect.value` and call `mount`. The `value` changes if you check/uncheck checkboxes or remove tags from the input.
|
|
103
|
+
**options** | Array[Object] ([]) | It is an array of objects ```{ name: String, value: String, children: [] }```, where children are the same array of objects. Do not use duplicated values.
|
|
104
|
+
**openLevel** | Number (0) | All groups will be opened to this level.
|
|
105
|
+
**appendToBody** | Boolean (false) | List will be appended to the body instead of the input container.
|
|
106
|
+
**alwaysOpen** | Boolean (false) | List will be always opened. You can use it for comfortable style changing. If you what to use it as an opened list, turn `staticList` to `true`.
|
|
107
|
+
**showTags** | Boolean (true) | Selected values look like tags. The false value shows results as '{count} elements selected'. You can change text if you use `tagsCountText` prop. For one selected element, you will see a name of this element.
|
|
108
|
+
**tagsCountText** | String ('elements selected') | This text will be shown if you use 'showTags'. This text will be inserted after the count of the selected elements - ```'{count} {tagsCountText}'```.
|
|
109
|
+
**clearable** | Boolean (true) | Clear icon is available.
|
|
110
|
+
**searchable** | Boolean (true) | Search is available.
|
|
111
|
+
**placeholder** | String ('Search...') | Placeholder text.
|
|
112
|
+
**grouped** | Boolean (true) | Show groups in the input and group leafs if all group selected.
|
|
113
|
+
**listSlotHtmlComponent** | HTMLElement (null) | It should be a HTML element, it will be append to the end of the list.
|
|
114
|
+
**disabled** | Boolean (false) | List will be disabled.
|
|
115
|
+
**emptyText** | String ('No results found...') | A empty list text.
|
|
116
|
+
**staticList** | Boolean (false) | Add the list as a static DOM element. List doesn't overlap content. This prop will be ignored if you use `appendToBody`.
|
|
116
117
|
|
|
117
118
|
### Emits
|
|
118
119
|
Name | Return Type | Description
|
|
119
120
|
------------- | ------------- | -------------
|
|
120
|
-
input | Array[String] | Returns selected ids without groups, only leafs.
|
|
121
|
+
**input** | Array[String] | Returns selected ids without groups, only leafs.
|
|
121
122
|
|
|
122
123
|
### Methods
|
|
123
124
|
Name | Params | Description
|
|
124
125
|
------------- | ------------- | -------------
|
|
125
|
-
updateValue | Array[String] | Update selected values.
|
|
126
|
-
mount | None | Helps to remount and update settings. Change settings that you need (treeselect.appendToBody = true), then call mount().
|
|
127
|
-
destroy | None | Deletes elements from the DOM. Call mount() to add treeselect to the DOM with previously saved internal data. If you need to recreate treeselect with default params - call
|
|
126
|
+
**updateValue** | Array[String] | Update selected values.
|
|
127
|
+
**mount** | None | Helps to remount and update settings. Change settings that you need (treeselect.appendToBody = true), then call mount().
|
|
128
|
+
**destroy** | None | Deletes elements from the DOM. Call mount() to add treeselect to the DOM with previously saved internal data. If you need to recreate treeselect with default params - call ```new Treeselect(options)```.
|
|
129
|
+
**focus** | None | Focuses treeselect input without open/close state changes.
|
|
130
|
+
**toggleOpenClose** | None | Open or close treeselect list and focus treeselect input.
|
|
128
131
|
|
|
129
132
|
### Notes
|
|
130
133
|
1) If you want to change the padding of the element you can use CSS selector. I've added **'group'** and **'level'** attributes, but you have to use **!important**.
|
package/dist/input.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import svg from"./svgIcons.js";class TreeselectInput{#htmlTagsSection=null;#htmlEditControl=null;#htmlOperators=null;#htmlArrow=null;#openEvent=new CustomEvent("open");#closeEvent=new CustomEvent("close");constructor({value:
|
|
1
|
+
import svg from"./svgIcons.js";class TreeselectInput{#htmlTagsSection=null;#htmlEditControl=null;#htmlOperators=null;#htmlArrow=null;#openEvent=new CustomEvent("open");#closeEvent=new CustomEvent("close");constructor({value:t,showTags:e,tagsCountText:s,clearable:a,isAlwaysOpened:i,searchable:n,placeholder:r,disabled:h}){this.value=t,this.showTags=e??!0,this.tagsCountText=s??"elements selected",this.searchable=n??!0,this.placeholder=r??"Search...",this.clearable=a??!0,this.isAlwaysOpened=i??!1,this.disabled=h??!1,this.isOpened=!1,this.searchText="",this.srcElement=this.#createTreeselectInput(),this.#updateDOM()}focus(){this.#htmlEditControl.focus()}blur(){this.isOpened&&this.#updateOpenClose()}updateValue(t){this.value=t,this.#updateTags(),this.#updateEditControl()}removeItem(e){this.value=this.value.filter(t=>t.id!==e),this.#emitInput(),this.#updateTags(),this.#updateEditControl()}clear(){this.value=[],this.searchText="",this.#emitSearch(""),this.#emitInput(),this.#updateTags(),this.#updateEditControl()}openClose(){this.#updateOpenClose()}#updateDOM(){this.#updateTags(),this.#updateEditControl(),this.#updateOperators()}#updateTags(){this.#htmlTagsSection.innerHTML="",this.showTags?this.#htmlTagsSection.append(...this.#createTags()):this.#htmlTagsSection.appendChild(this.#createCountElement())}#updateOperators(){const t=[];this.#htmlOperators.innerHTML="",this.clearable&&t.push(this.#createClearButton()),this.isAlwaysOpened||t.push(this.#createInputArrow(this.isOpened)),t.length&&this.#htmlOperators.append(...t)}#updateArrowDirection(){var t;this.isAlwaysOpened||(t=this.isOpened?svg.arrowUp:svg.arrowDown,this.#htmlArrow.innerHTML=t)}#updateEditControl(){this.value?.length?this.#htmlEditControl.removeAttribute("placeholder"):this.#htmlEditControl.setAttribute("placeholder",this.placeholder),this.searchable?this.srcElement.classList.remove("treeselect-input--unsearchable"):this.srcElement.classList.add("treeselect-input--unsearchable"),this.#htmlEditControl.value=this.searchText}#updateOpenClose(){this.isOpened=!this.isOpened,this.#updateArrowDirection(),this.isOpened?this.#emitOpen():this.#emitClose()}#createTreeselectInput(){const t=document.createElement("div");return t.classList.add("treeselect-input"),t.setAttribute("tabindex","-1"),this.#htmlTagsSection=this.#createTagsSection(),this.#htmlEditControl=this.#createControl(),this.#htmlOperators=this.#createOperators(),t.addEventListener("mousedown",t=>{t.preventDefault(),this.isOpened||this.#updateOpenClose(),this.focus()}),t.append(this.#htmlTagsSection,this.#htmlEditControl,this.#htmlOperators),t}#createTagsSection(){const t=document.createElement("div");return t.classList.add("treeselect-input__tags"),t}#createTags(){return this.value.map(e=>{const t=document.createElement("div");t.classList.add("treeselect-input__tags-element"),t.setAttribute("tabindex","-1"),t.setAttribute("tag-id",e.id),t.setAttribute("title",e.name);var s=this.#createTagName(e.name),a=this.#createTagCross();return t.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),this.focus(),this.removeItem(e.id)}),t.append(s,a),t})}#createTagName(t){const e=document.createElement("span");return e.classList.add("treeselect-input__tags-name"),e.innerHTML=t,e}#createTagCross(){const t=document.createElement("span");return t.classList.add("treeselect-input__tags-cross"),t.innerHTML=svg.cross,t}#createCountElement(){const t=document.createElement("span");return t.classList.add("treeselect-input__tags-count"),this.value.length?t.innerHTML=1===this.value.length?this.value[0].name:this.value.length+" "+this.tagsCountText:t.innerHTML="",t}#createControl(){const a=document.createElement("input");return a.classList.add("treeselect-input__edit"),this.disabled&&a.setAttribute("tabindex","-1"),a.addEventListener("keydown",t=>{"Backspace"!==t.key||this.searchText.length||!this.value.length||this.showTags||this.clear(),"Backspace"===t.key&&!this.searchText.length&&this.value.length&&this.removeItem(this.value[this.value.length-1].id),"Space"!==t.code||this.searchText&&this.searchable||this.#updateOpenClose()}),a.addEventListener("input",t=>{t.stopPropagation();var e=this.searchText,s=a.value.trim();0===e.length&&0===s.length?a.value="":(this.searchable?(this.#emitSearch(t.target.value),this.isOpened||this.#updateOpenClose()):a.value="",this.searchText=a.value)}),a}#createOperators(){const t=document.createElement("div");return t.classList.add("treeselect-input__operators"),t}#createClearButton(){const t=document.createElement("span");return t.classList.add("treeselect-input__clear"),t.setAttribute("tabindex","-1"),t.innerHTML=svg.clear,t.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation(),this.#htmlEditControl.focus(),(this.searchText.length||this.value.length)&&this.clear()}),t}#createInputArrow(t){return this.#htmlArrow=document.createElement("span"),this.#htmlArrow.classList.add("treeselect-input__arrow"),this.#htmlArrow.innerHTML=t?svg.arrowUp:svg.arrowDown,this.#htmlArrow.addEventListener("mousedown",t=>{t.stopPropagation(),t.preventDefault(),this.focus(),this.#updateOpenClose()}),this.#htmlArrow}#emitInput(){this.srcElement.dispatchEvent(new CustomEvent("input",{detail:this.value}))}#emitSearch(t){this.srcElement.dispatchEvent(new CustomEvent("search",{detail:t}))}#emitOpen(){this.srcElement.dispatchEvent(this.#openEvent)}#emitClose(){this.srcElement.dispatchEvent(this.#closeEvent)}}export default TreeselectInput;
|
package/dist/list.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import svg from"./svgIcons.js";const getFlatOptions=(e,i,l=0,c=0)=>e.reduce((e,t)=>{var s=!!t.children?.length;return e.push({id:t.value,name:t.name,childOf:l,isGroup:s,checked:!1,level:c,isClosed:i<=c&&s,hidden:i<c}),s&&(s=getFlatOptions(t.children,i,t.value,c+1),e.push(...s)),e},[]),checkAllChildrenInputs=({id:t,checked:s},i)=>{i.forEach(e=>{e.childOf===t&&(e.checked=s,e.isPartialChecked=!1,e.isGroup&&checkAllChildrenInputs(e,i))})},checkAllParentInputs=(t,e)=>{const s=e.find(e=>e.id===t),i=e.filter(e=>e.childOf===s.id);var l=i.every(e=>e.checked),c=i.some(e=>e.isPartialChecked||e.checked)&&!l,r=!l&&!c;l&&(s.checked=!0,s.isPartialChecked=!1),c&&(s.checked=!1,s.isPartialChecked=!0),r&&(s.checked=!1,s.isPartialChecked=!1),s.childOf&&checkAllParentInputs(s.childOf,e)},checkInput=({id:e,isGroup:t,childOf:s,checked:i},l)=>{t&&checkAllChildrenInputs({id:e,checked:i},l),s&&checkAllParentInputs(s,l)},updateValue=(t,s,e)=>{s.forEach(e=>{e.checked=!1,e.isPartialChecked=!1});const i=s.filter(e=>t.includes(e.id));i.forEach(e=>{e.checked=!0,e.isPartialChecked=!1,checkInput(e,s)}),updateDOM(s,e)},hideShowChildren=(t,{id:s,isClosed:i})=>{const e=t.filter(e=>e.childOf===s);e.forEach(e=>{e.hidden=i,e.isGroup&&!e.isClosed&&hideShowChildren(t,{id:e.id,isClosed:i})})},updateDOM=(l,c)=>{l.forEach(e=>{const t=c.querySelector(`[input-id="${e.id}"]`),s=getListItemByCheckbox(t);if(t.checked=e.checked,e.checked?s.classList.add("treeselect-list__item--checked"):s.classList.remove("treeselect-list__item--checked"),e.isPartialChecked?s.classList.add("treeselect-list__item--partial-checked"):s.classList.remove("treeselect-list__item--partial-checked"),e.isGroup){const i=s.querySelector(".treeselect-list__item-icon");e.isClosed?(s.classList.add("treeselect-list__item--closed"),i.innerHTML=svg.arrowRight):(s.classList.remove("treeselect-list__item--closed"),i.innerHTML=svg.arrowDown)}e.hidden?s.classList.add("treeselect-list__item--hidden"):s.classList.remove("treeselect-list__item--hidden"),updateLeftPaddingItems(e,s,l),updateCheckboxClasses(e,t)});var e=l.some(e=>!e.hidden);const t=c.querySelector(".treeselect-list__empty");e?t.classList.add("treeselect-list__empty--hidden"):t.classList.remove("treeselect-list__empty--hidden")},updateLeftPaddingItems=(t,e,s)=>{0===t.level?(s=s.some(e=>e.isGroup&&e.level===t.level),s=!t.isGroup&&s?"20px":"5px",e.style.paddingLeft=t.isGroup?"0":s):e.style.paddingLeft=t.isGroup?20*t.level+"px":20*t.level+20+"px",e.setAttribute("level",t.level),e.setAttribute("group",t.isGroup)},updateCheckboxClasses=(e,t)=>{const s=t.parentNode,i=s.querySelector(".treeselect-list__item-checkbox-icon");e.checked?i.innerHTML=svg.check:e.isPartialChecked?i.innerHTML=svg.partialCheck:i.innerHTML=""},getAllFlattedChildren=(s,i)=>i.reduce((e,t)=>(t.childOf===s&&(e.push(t),t.isGroup&&e.push(...getAllFlattedChildren(t.id,i))),e),[]),getAllFlattenParents=(s,i)=>i.reduce((e,t)=>(t.id===s&&(e.push(t),t.childOf&&e.push(...getAllFlattenParents(t.childOf,i))),e),[]),getGroupedValues=e=>{const{onlyGroupsIds:t,allItems:s}=e.reduce((e,t)=>(t.checked&&(t.isGroup&&e.onlyGroupsIds.push(t.id),e.allItems.push(t)),e),{onlyGroupsIds:[],allItems:[]});return s.filter(e=>!t.includes(e.childOf))},getCheckedValues=e=>e.filter(e=>e.checked&&!e.isGroup),getListItemByCheckbox=e=>{return e.parentNode.parentNode},validateOptions=e=>{const t=e.reduce((e,t)=>(e.allItems.includes(t.id)&&e.duplications.push(t.id),e.allItems.push(t.id),e),{duplications:[],allItems:[]})["duplications"];t.length&&console.error(`Validation: You have duplicated values: ${t.join(", ")}! You should use unique values.`)};class TreeselectList{#lastFocusedItem=null;#isMouseActionsAvailable=!0;constructor({options:e,value:t,openLevel:s,listSlotHtmlComponent:i,emptyText:l}){this.options=e,this.value=t,this.searchText="",this.openLevel=s??0,this.listSlotHtmlComponent=i,this.emptyText=l??"No results found...",this.flattedOptions=getFlatOptions(this.options,this.openLevel),this.flattedOptionsBeforeSearch=this.flattedOptions,this.selectedNodes={ids:[],groupedIds:[]},this.srcElement=this.#createList(),this.updateValue(this.value),validateOptions(this.flattedOptions)}updateValue(e){updateValue(e,this.flattedOptions,this.srcElement),this.#updateSelectedNodes()}updateSearchValue(i){if(i!==this.searchText){var e=""===this.searchText&&""!==i;if(this.searchText=i,e&&(this.flattedOptionsBeforeSearch=JSON.parse(JSON.stringify(this.flattedOptions))),""===this.searchText)return this.flattedOptions=this.flattedOptionsBeforeSearch.map(t=>{const e=this.flattedOptions.find(e=>e.id===t.id);return e.isClosed=t.isClosed,e.hidden=t.hidden,e}),this.flattedOptionsBeforeSearch=[],updateDOM(this.flattedOptions,this.srcElement),void this.focusFirstListElement();const s=this.flattedOptions.reduce((e,t)=>{var s;return t.name.toLowerCase().includes(i.toLowerCase())&&(e.push(t),t.isGroup&&(s=getAllFlattedChildren(t.id,this.flattedOptions),e.push(...s)),t.childOf&&(s=getAllFlattenParents(t.childOf,this.flattedOptions),e.push(...s))),e},[]);this.flattedOptions.forEach(t=>{s.some(e=>e.id===t.id)?(t.isGroup&&(t.isClosed=!1,hideShowChildren(this.flattedOptions,t)),t.hidden=!1):t.hidden=!0}),updateDOM(this.flattedOptions,this.srcElement),this.focusFirstListElement()}}callKeyAction(e){this.#isMouseActionsAvailable=!1;const t=this.srcElement.querySelector(".treeselect-list__item--focused");if("Enter"===e&&t&&t.dispatchEvent(new Event("mousedown")),"ArrowLeft"===e||"ArrowRight"===e){if(!t)return;const c=t.querySelector(".treeselect-list__item-checkbox"),r=c.getAttribute("input-id");var s=this.flattedOptions.find(e=>e.id===r);const o=t.querySelector(".treeselect-list__item-icon");"ArrowLeft"!==e||s.isClosed||o.dispatchEvent(new Event("mousedown")),"ArrowRight"===e&&s.isClosed&&o.dispatchEvent(new Event("mousedown"))}if("ArrowDown"===e||"ArrowUp"===e){const d=Array.from(this.srcElement.querySelectorAll(".treeselect-list__item-checkbox")).filter(e=>"none"!==window.getComputedStyle(getListItemByCheckbox(e)).display);if(d.length)if(t){s=d.findIndex(e=>getListItemByCheckbox(e).classList.contains("treeselect-list__item--focused"));const n=getListItemByCheckbox(d[s]);n.classList.remove("treeselect-list__item--focused");var s="ArrowDown"===e?s+1:s-1,i="ArrowDown"===e?0:d.length-1,i=d[s]??d[i],s=!d[s];const a=getListItemByCheckbox(i);a.classList.add("treeselect-list__item--focused");var i=this.srcElement.getBoundingClientRect(),l=a.getBoundingClientRect();s&&"ArrowDown"===e?this.srcElement.scroll(0,0):s&&"ArrowUp"===e?this.srcElement.scroll(0,this.srcElement.scrollHeight):i.y+i.height<l.y+l.height?this.srcElement.scroll(0,this.srcElement.scrollTop+l.height):i.y>l.y&&this.srcElement.scroll(0,this.srcElement.scrollTop-l.height)}else{const h=getListItemByCheckbox(d[0]);h.classList.add("treeselect-list__item--focused")}}}focusFirstListElement(){var e="treeselect-list__item--focused";const t=this.srcElement.querySelector("."+e);var s=Array.from(this.srcElement.querySelectorAll(".treeselect-list__item-checkbox")).filter(e=>"none"!==window.getComputedStyle(getListItemByCheckbox(e)).display);if(s.length){t&&t.classList.remove(e);const i=getListItemByCheckbox(s[0]);i.classList.add(e)}}#createList(){const e=[],t=document.createElement("div");t.classList.add("treeselect-list");var s=this.#getListHTML(this.options);if(e.push(...s),this.listSlotHtmlComponent){const i=document.createElement("div");i.classList.add("treeselect-list__slot"),i.appendChild(this.listSlotHtmlComponent),e.push(i)}s=this.#createEmptyList();return e.push(s),t.addEventListener("mouseout",e=>{e.stopPropagation(),this.#lastFocusedItem&&this.#isMouseActionsAvailable&&this.#lastFocusedItem.classList.add("treeselect-list__item--focused")}),t.addEventListener("mousemove",()=>{this.#isMouseActionsAvailable=!0}),t.append(...e),t}#getListHTML(e){return e.reduce((e,t)=>{if(t.children?.length){const i=this.#createGroupContainer(t);var s=this.#getListHTML(t.children);return i.append(...s),e.push(i),e}s=this.#createGroupItem(t,!1);return e.push(s),e},[])}#createGroupContainer(e){const t=document.createElement("div");t.setAttribute("group-container-id",e.value),t.classList.add("treeselect-list__group-container");e=this.#createGroupItem(e,!0);return t.appendChild(e),t}#createGroupItem(s,e){const t=document.createElement("div");t.setAttribute("tabindex","-1"),t.setAttribute("title",s.name),t.classList.add("treeselect-list__item"),e&&(e=this.#createArrow(),t.appendChild(e)),t.addEventListener("mouseover",()=>{this.#isMouseActionsAvailable&&this.#groupMouseAction(!0,t)},!0),t.addEventListener("mouseout",()=>{this.#isMouseActionsAvailable&&(this.#groupMouseAction(!1,t),this.#lastFocusedItem=t)},!0),t.addEventListener("mousedown",e=>{e.stopPropagation();const t=e.target.querySelector(".treeselect-list__item-checkbox");t.checked=!t.checked,this.#checkboxClickEvent(t,s)});var e=this.#createCheckbox(s),i=this.#createCheckboxLabel(s);return t.append(e,i),t}#createArrow(){const e=document.createElement("span");return e.setAttribute("tabindex","-1"),e.classList.add("treeselect-list__item-icon"),e.innerHTML=svg.arrowDown,e.addEventListener("mousedown",e=>{e.stopPropagation(),this.#arrowClickEvent(e)}),e}#createCheckbox(e){const t=document.createElement("div"),s=(t.classList.add("treeselect-list__item-checkbox-container"),document.createElement("span")),i=(s.classList.add("treeselect-list__item-checkbox-icon"),s.innerHTML="",document.createElement("input"));return i.setAttribute("tabindex","-1"),i.setAttribute("type","checkbox"),i.setAttribute("input-id",e.value),i.classList.add("treeselect-list__item-checkbox"),t.append(s,i),t}#createCheckboxLabel(e){const t=document.createElement("label");return t.innerHTML=e.name,t.classList.add("treeselect-list__item-label"),t}#createEmptyList(){const e=document.createElement("div"),t=(e.classList.add("treeselect-list__empty"),e.setAttribute("title",this.emptyText),document.createElement("span")),s=(t.classList.add("treeselect-list__empty-icon"),t.innerHTML=svg.attention,document.createElement("span"));return s.classList.add("treeselect-list__empty-text"),s.innerHTML=this.emptyText,e.append(t,s),e}#checkboxClickEvent(e,t){const s=this.flattedOptions.find(e=>e.id===t.value);s.checked=e.checked,s.isPartialChecked=!1,checkInput(s,this.flattedOptions),updateDOM(this.flattedOptions,this.srcElement),this.#emitInput()}#arrowClickEvent(e){const t=e.target.parentNode.querySelector("[input-id]"),s=t.getAttribute("input-id"),i=this.flattedOptions.find(e=>e.id===s);i.isClosed=!i.isClosed,hideShowChildren(this.flattedOptions,i),updateDOM(this.flattedOptions,this.srcElement),this.#emitArrowClick()}#groupMouseAction(e,t){const s="treeselect-list__item--focused";if(e){const i=Array.from(this.srcElement.querySelectorAll("."+s));i.length&&i.forEach(e=>e.classList.remove(s)),t.classList.add(s)}else t.classList.remove(s)}#updateSelectedNodes(){this.selectedNodes={ids:getCheckedValues(this.flattedOptions),groupedIds:getGroupedValues(this.flattedOptions)}}#emitArrowClick(){this.srcElement.dispatchEvent(new CustomEvent("arrow-click"))}#emitInput(){this.#updateSelectedNodes(),this.srcElement.dispatchEvent(new CustomEvent("input",{detail:this.selectedNodes}))}}export default TreeselectList;
|
|
1
|
+
import svg from"./svgIcons.js";const getFlatOptions=(e,i,l=0,c=0)=>e.reduce((e,t)=>{var s=!!t.children?.length;return e.push({id:t.value,name:t.name,childOf:l,isGroup:s,checked:!1,level:c,isClosed:i<=c&&s,hidden:i<c}),s&&(s=getFlatOptions(t.children,i,t.value,c+1),e.push(...s)),e},[]),checkAllChildrenInputs=({id:t,checked:s},i)=>{i.forEach(e=>{e.childOf===t&&(e.checked=s,e.isPartialChecked=!1,e.isGroup&&checkAllChildrenInputs(e,i))})},checkAllParentInputs=(t,e)=>{const s=e.find(e=>e.id===t),i=e.filter(e=>e.childOf===s.id);var l=i.every(e=>e.checked),c=i.some(e=>e.isPartialChecked||e.checked)&&!l,r=!l&&!c;l&&(s.checked=!0,s.isPartialChecked=!1),c&&(s.checked=!1,s.isPartialChecked=!0),r&&(s.checked=!1,s.isPartialChecked=!1),s.childOf&&checkAllParentInputs(s.childOf,e)},checkInput=({id:e,isGroup:t,childOf:s,checked:i},l)=>{t&&checkAllChildrenInputs({id:e,checked:i},l),s&&checkAllParentInputs(s,l)},updateValue=(t,s,e)=>{s.forEach(e=>{e.checked=!1,e.isPartialChecked=!1});const i=s.filter(e=>t.includes(e.id));i.forEach(e=>{e.checked=!0,e.isPartialChecked=!1,checkInput(e,s)}),updateDOM(s,e)},hideShowChildren=(t,{id:s,isClosed:i})=>{const e=t.filter(e=>e.childOf===s);e.forEach(e=>{e.hidden=i,e.isGroup&&!e.isClosed&&hideShowChildren(t,{id:e.id,isClosed:i})})},updateDOM=(l,c)=>{l.forEach(e=>{const t=c.querySelector(`[input-id="${e.id}"]`),s=getListItemByCheckbox(t);if(t.checked=e.checked,e.checked?s.classList.add("treeselect-list__item--checked"):s.classList.remove("treeselect-list__item--checked"),e.isPartialChecked?s.classList.add("treeselect-list__item--partial-checked"):s.classList.remove("treeselect-list__item--partial-checked"),e.isGroup){const i=s.querySelector(".treeselect-list__item-icon");e.isClosed?(s.classList.add("treeselect-list__item--closed"),i.innerHTML=svg.arrowRight):(s.classList.remove("treeselect-list__item--closed"),i.innerHTML=svg.arrowDown)}e.hidden?s.classList.add("treeselect-list__item--hidden"):s.classList.remove("treeselect-list__item--hidden"),updateLeftPaddingItems(e,s,l),updateCheckboxClasses(e,t)});var e=l.some(e=>!e.hidden);const t=c.querySelector(".treeselect-list__empty");e?t.classList.add("treeselect-list__empty--hidden"):t.classList.remove("treeselect-list__empty--hidden")},updateLeftPaddingItems=(t,e,s)=>{0===t.level?(s=s.some(e=>e.isGroup&&e.level===t.level),s=!t.isGroup&&s?"20px":"5px",e.style.paddingLeft=t.isGroup?"0":s):e.style.paddingLeft=t.isGroup?20*t.level+"px":20*t.level+20+"px",e.setAttribute("level",t.level),e.setAttribute("group",t.isGroup)},updateCheckboxClasses=(e,t)=>{const s=t.parentNode,i=s.querySelector(".treeselect-list__item-checkbox-icon");e.checked?i.innerHTML=svg.check:e.isPartialChecked?i.innerHTML=svg.partialCheck:i.innerHTML=""},getAllFlattedChildren=(s,i)=>i.reduce((e,t)=>(t.childOf===s&&(e.push(t),t.isGroup&&e.push(...getAllFlattedChildren(t.id,i))),e),[]),getAllFlattenParents=(s,i)=>i.reduce((e,t)=>(t.id===s&&(e.push(t),t.childOf&&e.push(...getAllFlattenParents(t.childOf,i))),e),[]),getGroupedValues=e=>{const{onlyGroupsIds:t,allItems:s}=e.reduce((e,t)=>(t.checked&&(t.isGroup&&e.onlyGroupsIds.push(t.id),e.allItems.push(t)),e),{onlyGroupsIds:[],allItems:[]});return s.filter(e=>!t.includes(e.childOf))},getCheckedValues=e=>e.filter(e=>e.checked&&!e.isGroup),getListItemByCheckbox=e=>{return e.parentNode.parentNode},validateOptions=e=>{const t=e.reduce((e,t)=>(e.allItems.includes(t.id)&&e.duplications.push(t.id),e.allItems.push(t.id),e),{duplications:[],allItems:[]})["duplications"];t.length&&console.error(`Validation: You have duplicated values: ${t.join(", ")}! You should use unique values.`)};class TreeselectList{#lastFocusedItem=null;#isMouseActionsAvailable=!0;constructor({options:e,value:t,openLevel:s,listSlotHtmlComponent:i,emptyText:l}){this.options=e,this.value=t,this.searchText="",this.openLevel=s??0,this.listSlotHtmlComponent=i,this.emptyText=l??"No results found...",this.flattedOptions=getFlatOptions(this.options,this.openLevel),this.flattedOptionsBeforeSearch=this.flattedOptions,this.selectedNodes={nodes:[],groupedNodes:[]},this.srcElement=this.#createList(),this.updateValue(this.value),validateOptions(this.flattedOptions)}updateValue(e){updateValue(e,this.flattedOptions,this.srcElement),this.#updateSelectedNodes()}updateSearchValue(i){if(i!==this.searchText){var e=""===this.searchText&&""!==i;if(this.searchText=i,e&&(this.flattedOptionsBeforeSearch=JSON.parse(JSON.stringify(this.flattedOptions))),""===this.searchText)return this.flattedOptions=this.flattedOptionsBeforeSearch.map(t=>{const e=this.flattedOptions.find(e=>e.id===t.id);return e.isClosed=t.isClosed,e.hidden=t.hidden,e}),this.flattedOptionsBeforeSearch=[],updateDOM(this.flattedOptions,this.srcElement),void this.focusFirstListElement();const s=this.flattedOptions.reduce((e,t)=>{var s;return t.name.toLowerCase().includes(i.toLowerCase())&&(e.push(t),t.isGroup&&(s=getAllFlattedChildren(t.id,this.flattedOptions),e.push(...s)),t.childOf&&(s=getAllFlattenParents(t.childOf,this.flattedOptions),e.push(...s))),e},[]);this.flattedOptions.forEach(t=>{s.some(e=>e.id===t.id)?(t.isGroup&&(t.isClosed=!1,hideShowChildren(this.flattedOptions,t)),t.hidden=!1):t.hidden=!0}),updateDOM(this.flattedOptions,this.srcElement),this.focusFirstListElement()}}callKeyAction(e){this.#isMouseActionsAvailable=!1;const t=this.srcElement.querySelector(".treeselect-list__item--focused");if("Enter"===e&&t&&t.dispatchEvent(new Event("mousedown")),"ArrowLeft"===e||"ArrowRight"===e){if(!t)return;const c=t.querySelector(".treeselect-list__item-checkbox"),r=c.getAttribute("input-id");var s=this.flattedOptions.find(e=>e.id===r);const o=t.querySelector(".treeselect-list__item-icon");"ArrowLeft"!==e||s.isClosed||o.dispatchEvent(new Event("mousedown")),"ArrowRight"===e&&s.isClosed&&o.dispatchEvent(new Event("mousedown"))}if("ArrowDown"===e||"ArrowUp"===e){const n=Array.from(this.srcElement.querySelectorAll(".treeselect-list__item-checkbox")).filter(e=>"none"!==window.getComputedStyle(getListItemByCheckbox(e)).display);if(n.length)if(t){s=n.findIndex(e=>getListItemByCheckbox(e).classList.contains("treeselect-list__item--focused"));const d=getListItemByCheckbox(n[s]);d.classList.remove("treeselect-list__item--focused");var s="ArrowDown"===e?s+1:s-1,i="ArrowDown"===e?0:n.length-1,i=n[s]??n[i],s=!n[s];const a=getListItemByCheckbox(i);a.classList.add("treeselect-list__item--focused");var i=this.srcElement.getBoundingClientRect(),l=a.getBoundingClientRect();s&&"ArrowDown"===e?this.srcElement.scroll(0,0):s&&"ArrowUp"===e?this.srcElement.scroll(0,this.srcElement.scrollHeight):i.y+i.height<l.y+l.height?this.srcElement.scroll(0,this.srcElement.scrollTop+l.height):i.y>l.y&&this.srcElement.scroll(0,this.srcElement.scrollTop-l.height)}else{const h=getListItemByCheckbox(n[0]);h.classList.add("treeselect-list__item--focused")}}}focusFirstListElement(){var e="treeselect-list__item--focused";const t=this.srcElement.querySelector("."+e);var s=Array.from(this.srcElement.querySelectorAll(".treeselect-list__item-checkbox")).filter(e=>"none"!==window.getComputedStyle(getListItemByCheckbox(e)).display);if(s.length){t&&t.classList.remove(e);const i=getListItemByCheckbox(s[0]);i.classList.add(e)}}#createList(){const e=[],t=document.createElement("div");t.classList.add("treeselect-list");var s=this.#getListHTML(this.options);if(e.push(...s),this.listSlotHtmlComponent){const i=document.createElement("div");i.classList.add("treeselect-list__slot"),i.appendChild(this.listSlotHtmlComponent),e.push(i)}s=this.#createEmptyList();return e.push(s),t.addEventListener("mouseout",e=>{e.stopPropagation(),this.#lastFocusedItem&&this.#isMouseActionsAvailable&&this.#lastFocusedItem.classList.add("treeselect-list__item--focused")}),t.addEventListener("mousemove",()=>{this.#isMouseActionsAvailable=!0}),t.append(...e),t}#getListHTML(e){return e.reduce((e,t)=>{if(t.children?.length){const i=this.#createGroupContainer(t);var s=this.#getListHTML(t.children);return i.append(...s),e.push(i),e}s=this.#createGroupItem(t,!1);return e.push(s),e},[])}#createGroupContainer(e){const t=document.createElement("div");t.setAttribute("group-container-id",e.value),t.classList.add("treeselect-list__group-container");e=this.#createGroupItem(e,!0);return t.appendChild(e),t}#createGroupItem(s,e){const t=document.createElement("div");t.setAttribute("tabindex","-1"),t.setAttribute("title",s.name),t.classList.add("treeselect-list__item"),e&&(e=this.#createArrow(),t.appendChild(e)),t.addEventListener("mouseover",()=>{this.#isMouseActionsAvailable&&this.#groupMouseAction(!0,t)},!0),t.addEventListener("mouseout",()=>{this.#isMouseActionsAvailable&&(this.#groupMouseAction(!1,t),this.#lastFocusedItem=t)},!0),t.addEventListener("mousedown",e=>{e.stopPropagation();const t=e.target.querySelector(".treeselect-list__item-checkbox");t.checked=!t.checked,this.#checkboxClickEvent(t,s)});var e=this.#createCheckbox(s),i=this.#createCheckboxLabel(s);return t.append(e,i),t}#createArrow(){const e=document.createElement("span");return e.setAttribute("tabindex","-1"),e.classList.add("treeselect-list__item-icon"),e.innerHTML=svg.arrowDown,e.addEventListener("mousedown",e=>{e.stopPropagation(),this.#arrowClickEvent(e)}),e}#createCheckbox(e){const t=document.createElement("div"),s=(t.classList.add("treeselect-list__item-checkbox-container"),document.createElement("span")),i=(s.classList.add("treeselect-list__item-checkbox-icon"),s.innerHTML="",document.createElement("input"));return i.setAttribute("tabindex","-1"),i.setAttribute("type","checkbox"),i.setAttribute("input-id",e.value),i.classList.add("treeselect-list__item-checkbox"),t.append(s,i),t}#createCheckboxLabel(e){const t=document.createElement("label");return t.innerHTML=e.name,t.classList.add("treeselect-list__item-label"),t}#createEmptyList(){const e=document.createElement("div"),t=(e.classList.add("treeselect-list__empty"),e.setAttribute("title",this.emptyText),document.createElement("span")),s=(t.classList.add("treeselect-list__empty-icon"),t.innerHTML=svg.attention,document.createElement("span"));return s.classList.add("treeselect-list__empty-text"),s.innerHTML=this.emptyText,e.append(t,s),e}#checkboxClickEvent(e,t){const s=this.flattedOptions.find(e=>e.id===t.value);s.checked=e.checked,s.isPartialChecked=!1,checkInput(s,this.flattedOptions),updateDOM(this.flattedOptions,this.srcElement),this.#emitInput()}#arrowClickEvent(e){const t=e.target.parentNode.querySelector("[input-id]"),s=t.getAttribute("input-id"),i=this.flattedOptions.find(e=>e.id===s);i.isClosed=!i.isClosed,hideShowChildren(this.flattedOptions,i),updateDOM(this.flattedOptions,this.srcElement),this.#emitArrowClick()}#groupMouseAction(e,t){const s="treeselect-list__item--focused";if(e){const i=Array.from(this.srcElement.querySelectorAll("."+s));i.length&&i.forEach(e=>e.classList.remove(s)),t.classList.add(s)}else t.classList.remove(s)}#updateSelectedNodes(){this.selectedNodes={nodes:getCheckedValues(this.flattedOptions),groupedNodes:getGroupedValues(this.flattedOptions)}}#emitArrowClick(){this.srcElement.dispatchEvent(new CustomEvent("arrow-click"))}#emitInput(){this.#updateSelectedNodes(),this.srcElement.dispatchEvent(new CustomEvent("input",{detail:this.selectedNodes}))}}export default TreeselectList;
|
package/dist/treeselect-js.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import TreeselectInput from"./input.js";import TreeselectList from"./list.js";const validateProps=({parentHtmlContainer:e,staticList:t,appendToBody:s})=>{e||console.error("Validation: parentHtmlContainer prop is required!"),t&&s&&console.error("Validation: You should set staticList to false if you use appendToBody!")};class Treeselect{#htmlContainer=null;#treeselectList=null;#treeselectInput=null;#containerResizer=null;#scrollEvent=null;#resizeEvent=null;#focusEvent=null;#blurEvent=null
|
|
1
|
+
import TreeselectInput from"./input.js";import TreeselectList from"./list.js";const validateProps=({parentHtmlContainer:e,staticList:t,appendToBody:s})=>{e||console.error("Validation: parentHtmlContainer prop is required!"),t&&s&&console.error("Validation: You should set staticList to false if you use appendToBody!")},getOnlyIds=e=>e.map(e=>e.id);class Treeselect{#htmlContainer=null;#treeselectList=null;#treeselectInput=null;#containerResizer=null;#scrollEvent=null;#resizeEvent=null;#focusEvent=null;#blurEvent=null;constructor({parentHtmlContainer:e,value:t,options:s,openLevel:i,appendToBody:n,alwaysOpen:l,showTags:r,tagsCountText:o,clearable:c,searchable:a,placeholder:d,grouped:h,listSlotHtmlComponent:p,disabled:u,emptyText:m,staticList:L}){validateProps({parentHtmlContainer:e,staticList:L,appendToBody:n}),this.parentHtmlContainer=e,this.value=t??[],this.options=s??[],this.openLevel=i??0,this.appendToBody=n??!0,this.alwaysOpen=l&&!u,this.showTags=r??!0,this.tagsCountText=o??"elements selected",this.clearable=c??!0,this.searchable=a??!0,this.placeholder=d??"Search...",this.grouped=h??!0,this.listSlotHtmlComponent=p??null,this.disabled=u??!1,this.emptyText=m??"No results found...",this.staticList=L&&!this.appendToBody,this.isListOpened=!1,this.srcElement=null,this.mount()}mount(){this.destroy(),this.srcElement=this.#createTreeselect(),this.#scrollEvent=this.scrollWindowHandler.bind(this),this.#resizeEvent=this.scrollWindowHandler.bind(this),this.#focusEvent=this.focusWindowHandler.bind(this),this.#blurEvent=this.blurWindowHandler.bind(this),this.alwaysOpen&&this.#treeselectInput.openClose(),this.disabled&&this.srcElement.classList.add("treeselect--disabled")}updateValue(e){const t=this.#treeselectList;t.updateValue(e);var{groupedNodes:e,nodes:s}=t.selectedNodes,e=this.grouped?e:s;this.#treeselectInput.updateValue(e)}destroy(){this.srcElement&&(this.#closeList(),this.srcElement.innerHTML="",this.srcElement=null,this.#removeOutsideListeners(!0))}focus(){this.#treeselectInput&&this.#treeselectInput.focus()}toggleOpenClose(){this.#treeselectInput&&(this.#treeselectInput.openClose(),this.#treeselectInput.focus())}#createTreeselect(){const e=this.parentHtmlContainer,t=(e.classList.add("treeselect"),new TreeselectList({options:this.options,value:this.value,openLevel:this.openLevel,listSlotHtmlComponent:this.listSlotHtmlComponent,emptyText:this.emptyText}));var{groupedNodes:s,nodes:i}=t.selectedNodes;const n=new TreeselectInput({value:this.grouped?s:i,showTags:this.showTags,tagsCountText:this.tagsCountText,clearable:this.clearable,isAlwaysOpened:this.alwaysOpen,searchable:this.searchable,placeholder:this.placeholder,disabled:this.disabled});return this.appendToBody&&(this.#containerResizer=new ResizeObserver(()=>{this.updateListPosition()})),n.srcElement.addEventListener("input",e=>{e=getOnlyIds(e.detail),t.updateValue(e),e=t.selectedNodes.nodes;this.value=getOnlyIds(e),this.#emitInput()}),n.srcElement.addEventListener("open",()=>this.#openList()),n.srcElement.addEventListener("keydown",e=>{this.isListOpened&&t.callKeyAction(e.key)}),n.srcElement.addEventListener("search",e=>{t.updateSearchValue(e.detail),this.updateListPosition()}),n.srcElement.addEventListener("focus",()=>{this.#updateFocusClasses(!0),document.addEventListener("mousedown",this.#focusEvent,!0),document.addEventListener("focus",this.#focusEvent,!0),window.addEventListener("blur",this.#blurEvent)},!0),this.alwaysOpen||n.srcElement.addEventListener("close",()=>{this.#closeList()}),t.srcElement.addEventListener("mouseup",()=>{n.focus()},!0),t.srcElement.addEventListener("input",e=>{var{groupedNodes:e,nodes:t}=e.detail,e=this.grouped?e:t;n.updateValue(e),this.value=getOnlyIds(t),n.focus(),this.#emitInput()}),t.srcElement.addEventListener("arrow-click",()=>{n.focus(),this.updateListPosition()}),this.#htmlContainer=e,this.#treeselectList=t,this.#treeselectInput=n,e.append(n.srcElement),e}#openList(){this.isListOpened=!0,window.addEventListener("scroll",this.#scrollEvent,!0),window.addEventListener("resize",this.#resizeEvent),this.appendToBody?(document.body.appendChild(this.#treeselectList.srcElement),this.#containerResizer.observe(this.#htmlContainer)):this.#htmlContainer.appendChild(this.#treeselectList.srcElement),this.updateListPosition(),this.#updateOpenCloseClasses(!0),this.#treeselectList.focusFirstListElement()}#closeList(){this.isListOpened=!1,window.removeEventListener("scroll",this.#scrollEvent,!0),window.removeEventListener("resize",this.#resizeEvent),(this.appendToBody?document.body:this.#htmlContainer).contains(this.#treeselectList.srcElement)&&(this.appendToBody?(document.body.removeChild(this.#treeselectList.srcElement),this.#containerResizer?.disconnect()):this.#htmlContainer.removeChild(this.#treeselectList.srcElement),this.#updateOpenCloseClasses(!1))}#updateDirectionClasses(e,t){var s=t?"treeselect-list--top-to-body":"treeselect-list--top",t=t?"treeselect-list--bottom-to-body":"treeselect-list--bottom";e?(this.#treeselectList.srcElement.classList.add(s),this.#treeselectList.srcElement.classList.remove(t),this.#treeselectInput.srcElement.classList.add("treeselect-input--top"),this.#treeselectInput.srcElement.classList.remove("treeselect-input--bottom")):(this.#treeselectList.srcElement.classList.remove(s),this.#treeselectList.srcElement.classList.add(t),this.#treeselectInput.srcElement.classList.remove("treeselect-input--top"),this.#treeselectInput.srcElement.classList.add("treeselect-input--bottom"))}#updateFocusClasses(e){e?(this.#treeselectInput.srcElement.classList.add("treeselect-input--focused"),this.#treeselectList.srcElement.classList.add("treeselect-list--focused")):(this.#treeselectInput.srcElement.classList.remove("treeselect-input--focused"),this.#treeselectList.srcElement.classList.remove("treeselect-list--focused"))}#updateOpenCloseClasses(e){e?this.#treeselectInput.srcElement.classList.add("treeselect-input--opened"):this.#treeselectInput.srcElement.classList.remove("treeselect-input--opened"),this.staticList?this.#treeselectList.srcElement.classList.add("treeselect-list--static"):this.#treeselectList.srcElement.classList.remove("treeselect-list--static")}#removeOutsideListeners(e){this.alwaysOpen&&!e||(window.removeEventListener("scroll",this.#scrollEvent,!0),window.removeEventListener("resize",this.#resizeEvent)),document.removeEventListener("click",this.#focusEvent,!0),document.removeEventListener("focus",this.#focusEvent,!0),window.removeEventListener("blur",this.#blurEvent)}scrollWindowHandler(){this.updateListPosition()}focusWindowHandler(e){this.#htmlContainer.contains(e.target)||this.#treeselectList.srcElement.contains(e.target)||(this.#treeselectInput.blur(),this.#removeOutsideListeners(),this.#updateFocusClasses(!1))}blurWindowHandler(){this.#treeselectInput.blur(),this.#removeOutsideListeners(),this.#updateFocusClasses(!1)}updateListPosition(){const e=this.#treeselectList.srcElement,t=(e.style.transform=null,this.#htmlContainer);var{y:s,height:i}=e.getBoundingClientRect(),{x:n,y:l,height:r,width:o}=t.getBoundingClientRect(),c=window.innerHeight-l-r,c=c<l&&i<=l&&c<i,i=(this.appendToBody&&(e.style.transform=c?`translateY(${l-s-i}px)`:`translateY(${l+r-s}px)`,e.style.width=o+"px",e.style.left=n+window.scrollX+"px"),c?"top":"bottom");e.getAttribute("direction")!==i&&(e.setAttribute("direction",i),this.#updateDirectionClasses(c,this.appendToBody))}#emitInput(){this.srcElement.dispatchEvent(new CustomEvent("input",{detail:this.value}))}}export default Treeselect;
|
package/package.json
CHANGED
package/src/input.js
CHANGED
|
@@ -11,6 +11,7 @@ class TreeselectInput {
|
|
|
11
11
|
constructor ({
|
|
12
12
|
value,
|
|
13
13
|
showTags,
|
|
14
|
+
tagsCountText,
|
|
14
15
|
clearable,
|
|
15
16
|
isAlwaysOpened,
|
|
16
17
|
searchable,
|
|
@@ -20,6 +21,7 @@ class TreeselectInput {
|
|
|
20
21
|
this.value = value
|
|
21
22
|
|
|
22
23
|
this.showTags = showTags ?? true
|
|
24
|
+
this.tagsCountText = tagsCountText ?? 'elements selected'
|
|
23
25
|
this.searchable = searchable ?? true
|
|
24
26
|
this.placeholder = placeholder ?? 'Search...'
|
|
25
27
|
this.clearable = clearable ?? true
|
|
@@ -221,7 +223,7 @@ class TreeselectInput {
|
|
|
221
223
|
|
|
222
224
|
countEl.innerHTML = this.value.length === 1
|
|
223
225
|
? this.value[0].name
|
|
224
|
-
: `${this.value.length}
|
|
226
|
+
: `${this.value.length} ${this.tagsCountText}`
|
|
225
227
|
|
|
226
228
|
return countEl
|
|
227
229
|
}
|
package/src/list.js
CHANGED
|
@@ -277,7 +277,7 @@ class TreeselectList {
|
|
|
277
277
|
|
|
278
278
|
this.flattedOptions = getFlatOptions(this.options, this.openLevel)
|
|
279
279
|
this.flattedOptionsBeforeSearch = this.flattedOptions
|
|
280
|
-
this.selectedNodes = {
|
|
280
|
+
this.selectedNodes = { nodes: [], groupedNodes: [] }
|
|
281
281
|
this.srcElement = this.#createList()
|
|
282
282
|
|
|
283
283
|
this.updateValue(this.value)
|
|
@@ -654,8 +654,8 @@ class TreeselectList {
|
|
|
654
654
|
|
|
655
655
|
#updateSelectedNodes () {
|
|
656
656
|
this.selectedNodes = {
|
|
657
|
-
|
|
658
|
-
|
|
657
|
+
nodes: getCheckedValues(this.flattedOptions),
|
|
658
|
+
groupedNodes: getGroupedValues(this.flattedOptions)
|
|
659
659
|
}
|
|
660
660
|
}
|
|
661
661
|
|
package/src/treeselect-js.js
CHANGED
|
@@ -12,6 +12,8 @@ const validateProps = ({ parentHtmlContainer, staticList, appendToBody }) => {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const getOnlyIds = (nodes) => nodes.map(node => node.id)
|
|
16
|
+
|
|
15
17
|
class Treeselect {
|
|
16
18
|
// Components
|
|
17
19
|
#htmlContainer = null
|
|
@@ -27,9 +29,6 @@ class Treeselect {
|
|
|
27
29
|
#focusEvent = null
|
|
28
30
|
#blurEvent = null
|
|
29
31
|
|
|
30
|
-
// State
|
|
31
|
-
#isListOpened = false
|
|
32
|
-
|
|
33
32
|
constructor ({
|
|
34
33
|
parentHtmlContainer,
|
|
35
34
|
value,
|
|
@@ -38,6 +37,7 @@ class Treeselect {
|
|
|
38
37
|
appendToBody,
|
|
39
38
|
alwaysOpen,
|
|
40
39
|
showTags,
|
|
40
|
+
tagsCountText,
|
|
41
41
|
clearable,
|
|
42
42
|
searchable,
|
|
43
43
|
placeholder,
|
|
@@ -60,6 +60,7 @@ class Treeselect {
|
|
|
60
60
|
this.appendToBody = appendToBody ?? true
|
|
61
61
|
this.alwaysOpen = alwaysOpen && !disabled
|
|
62
62
|
this.showTags = showTags ?? true
|
|
63
|
+
this.tagsCountText = tagsCountText ?? 'elements selected'
|
|
63
64
|
this.clearable = clearable ?? true
|
|
64
65
|
this.searchable = searchable ?? true
|
|
65
66
|
this.placeholder = placeholder ?? 'Search...'
|
|
@@ -69,6 +70,8 @@ class Treeselect {
|
|
|
69
70
|
this.emptyText = emptyText ?? 'No results found...'
|
|
70
71
|
this.staticList = staticList && !this.appendToBody
|
|
71
72
|
|
|
73
|
+
// State
|
|
74
|
+
this.isListOpened = false
|
|
72
75
|
this.srcElement = null
|
|
73
76
|
|
|
74
77
|
this.mount()
|
|
@@ -97,8 +100,8 @@ class Treeselect {
|
|
|
97
100
|
updateValue (newValue) {
|
|
98
101
|
const list = this.#treeselectList
|
|
99
102
|
list.updateValue(newValue)
|
|
100
|
-
const {
|
|
101
|
-
const inputNewValue = this.grouped ?
|
|
103
|
+
const {groupedNodes, nodes } = list.selectedNodes
|
|
104
|
+
const inputNewValue = this.grouped ? groupedNodes : nodes
|
|
102
105
|
this.#treeselectInput.updateValue(inputNewValue)
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -111,6 +114,19 @@ class Treeselect {
|
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
|
|
117
|
+
focus () {
|
|
118
|
+
if (this.#treeselectInput) {
|
|
119
|
+
this.#treeselectInput.focus()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
toggleOpenClose () {
|
|
124
|
+
if (this.#treeselectInput) {
|
|
125
|
+
this.#treeselectInput.openClose()
|
|
126
|
+
this.#treeselectInput.focus()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
#createTreeselect () {
|
|
115
131
|
const container = this.parentHtmlContainer
|
|
116
132
|
container.classList.add('treeselect')
|
|
@@ -123,10 +139,11 @@ class Treeselect {
|
|
|
123
139
|
emptyText: this.emptyText
|
|
124
140
|
})
|
|
125
141
|
|
|
126
|
-
const {
|
|
142
|
+
const {groupedNodes, nodes } = list.selectedNodes
|
|
127
143
|
const input = new TreeselectInput({
|
|
128
|
-
value: this.grouped ?
|
|
144
|
+
value: this.grouped ? groupedNodes : nodes,
|
|
129
145
|
showTags: this.showTags,
|
|
146
|
+
tagsCountText: this.tagsCountText,
|
|
130
147
|
clearable: this.clearable,
|
|
131
148
|
isAlwaysOpened: this.alwaysOpen,
|
|
132
149
|
searchable: this.searchable,
|
|
@@ -142,14 +159,15 @@ class Treeselect {
|
|
|
142
159
|
|
|
143
160
|
// Input events
|
|
144
161
|
input.srcElement.addEventListener('input', (e) => {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
list.
|
|
162
|
+
const inputIds = getOnlyIds(e.detail)
|
|
163
|
+
list.updateValue(inputIds)
|
|
164
|
+
const { nodes } = list.selectedNodes
|
|
165
|
+
this.value = getOnlyIds(nodes)
|
|
148
166
|
this.#emitInput()
|
|
149
167
|
})
|
|
150
168
|
input.srcElement.addEventListener('open', () => this.#openList())
|
|
151
169
|
input.srcElement.addEventListener('keydown', (e) => {
|
|
152
|
-
if (this
|
|
170
|
+
if (this.isListOpened) {
|
|
153
171
|
list.callKeyAction(e.key)
|
|
154
172
|
}
|
|
155
173
|
})
|
|
@@ -175,10 +193,10 @@ class Treeselect {
|
|
|
175
193
|
input.focus()
|
|
176
194
|
}, true)
|
|
177
195
|
list.srcElement.addEventListener('input', (e) => {
|
|
178
|
-
const {
|
|
179
|
-
const inputIds = this.grouped ?
|
|
196
|
+
const {groupedNodes, nodes } = e.detail
|
|
197
|
+
const inputIds = this.grouped ? groupedNodes : nodes
|
|
180
198
|
input.updateValue(inputIds)
|
|
181
|
-
this.value =
|
|
199
|
+
this.value = getOnlyIds(nodes)
|
|
182
200
|
input.focus()
|
|
183
201
|
this.#emitInput()
|
|
184
202
|
})
|
|
@@ -197,7 +215,7 @@ class Treeselect {
|
|
|
197
215
|
}
|
|
198
216
|
|
|
199
217
|
#openList () {
|
|
200
|
-
this
|
|
218
|
+
this.isListOpened = true
|
|
201
219
|
|
|
202
220
|
window.addEventListener('scroll', this.#scrollEvent, true)
|
|
203
221
|
window.addEventListener('resize', this.#resizeEvent)
|
|
@@ -215,7 +233,7 @@ class Treeselect {
|
|
|
215
233
|
}
|
|
216
234
|
|
|
217
235
|
#closeList () {
|
|
218
|
-
this
|
|
236
|
+
this.isListOpened = false
|
|
219
237
|
|
|
220
238
|
window.removeEventListener('scroll', this.#scrollEvent, true)
|
|
221
239
|
window.removeEventListener('resize', this.#resizeEvent)
|