tail-select-rails 1.0.2 → 1.0.4
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.
- checksums.yaml +4 -4
- data/Readme.md +2 -1
- data/app/assets/javascripts/tail.select.js +1567 -523
- data/app/assets/stylesheets/tail.select.css +383 -181
- metadata +2 -3
- data/app/assets/javascripts/tail.select.min.js +0 -11
@@ -1,11 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* tail.select - The vanilla JavaScript solution to make your <select> fields awesome!
|
3
|
-
*
|
4
|
-
* @author Ciprian Popescu <getbutterfly@gmail.com>
|
5
|
-
* @version 1.0.2
|
6
|
-
* @url https://getbutterfly.com/tail-select/
|
7
|
-
* @github https://github.com/wolffe/tail.select.js
|
8
|
-
* @license MIT License
|
9
|
-
* @copyright Copyright 2020 - 2024 Ciprian Popescu <getbutterfly@gmail.com>
|
10
|
-
*/
|
11
|
-
const tail={select:function(selector,options={}){const defaultOptions={multiTags:!1,multiCounter:!0,theme:"light",classNames:"tail-default",strings:{all:"All",none:"None",placeholder:"Select an option...",search:"Type in to search..."}},opts={...defaultOptions,...options},{multiTags:multiTags,multiCounter:multiCounter,theme:theme,classNames:classNames,strings:strings}=opts,originalSelects=document.querySelectorAll(selector);originalSelects.forEach(originalSelect=>{originalSelect.style.display="none";const customDropdown=document.createElement("div");customDropdown.classList.add("tail-select"),customDropdown.classList.add(originalSelect.id),customDropdown.classList.add(opts.classNames),customDropdown.dataset.theme=`tail-theme--${opts.theme}`,originalSelect.multiple?customDropdown.classList.add("tail--multiple"):customDropdown.classList.add("tail--single");const searchInput=document.createElement("input");searchInput.type="text",searchInput.classList.add("tail--search"),searchInput.placeholder=strings.placeholder||"Select an option...",searchInput.addEventListener("focus",()=>{searchInput.placeholder=strings.search||"Type in to search..."}),searchInput.addEventListener("blur",()=>{searchInput.placeholder=strings.placeholder||"Select an option..."}),searchInput.addEventListener("input",()=>filterOptions(originalSelect,searchInput));const tailFloatingToolbar=document.createElement("div");tailFloatingToolbar.classList.add("tail--toolbar");const toggleAllCheckbox=document.createElement("input");toggleAllCheckbox.type="checkbox",toggleAllCheckbox.value=strings.all||"All",toggleAllCheckbox.addEventListener("change",()=>toggleAll(originalSelect,toggleAllCheckbox));const toggleAllLabel=document.createElement("label");toggleAllLabel.textContent=strings.all||"All",toggleAllLabel.classList.add("all"),toggleAllLabel.appendChild(toggleAllCheckbox);const uncheckAllButton=document.createElement("button");if(uncheckAllButton.type="button",uncheckAllButton.textContent=strings.none||"None",uncheckAllButton.classList.add("uncheck"),uncheckAllButton.addEventListener("click",()=>uncheckAll(originalSelect)),opts.multiCounter){const counter=document.createElement("span");counter.textContent="0",counter.classList.add("tail--counter"),customDropdown.appendChild(counter)}const nestedList=document.createElement("div");nestedList.classList.add("tail--nested-dropdown"),nestedList.style.display="none",customDropdown.appendChild(searchInput),customDropdown.appendChild(tailFloatingToolbar),customDropdown.appendChild(nestedList),tailFloatingToolbar.appendChild(toggleAllLabel),tailFloatingToolbar.appendChild(uncheckAllButton),originalSelect.insertAdjacentElement("afterend",customDropdown);const selectedOptionsList=document.createElement("ul");function buildNestedList(){const fragment=document.createDocumentFragment(),optgroups=originalSelect.getElementsByTagName("optgroup");if(optgroups.length>0)for(let i=0;i<optgroups.length;i++){const optgroup=optgroups[i],optgroupItem=document.createElement("div");optgroupItem.classList.add("tail--optgroup");const optgroupLabel=document.createElement("label"),optgroupCheckbox=document.createElement("input");optgroupCheckbox.type="checkbox",optgroupCheckbox.value=optgroup.label,optgroupCheckbox.addEventListener("change",()=>toggleOptgroup(optgroupCheckbox)),optgroupLabel.appendChild(optgroupCheckbox);const optgroupLabelText=document.createElement("span");optgroupLabelText.textContent=optgroup.label,optgroupLabelText.classList.add("tail--optgroup-label"),optgroupLabel.appendChild(optgroupLabelText),optgroupItem.appendChild(optgroupLabel);const nestedOptionsList=document.createElement("div");nestedOptionsList.setAttribute("role","listbox"),nestedOptionsList.classList.add("tail--nested-dropdown-list");const options=optgroup.getElementsByTagName("option");for(let j=0;j<options.length;j++){const option=options[j],optionItem=document.createElement("div");optionItem.classList.add("tail--nested-dropdown-item");const optionCheckbox=document.createElement("input");optionCheckbox.type="checkbox",optionCheckbox.value=option.textContent;const optionLabel=document.createElement("label"),optionLabelText=document.createElement("span");optionLabelText.textContent=option.textContent,option.dataset.description&&(optionLabelText.innerHTML+=`<small>${option.dataset.description}</small>`),option.selected&&option.hasAttribute("selected")&&(optionCheckbox.checked=!0,updateCounter(originalSelect),updateCustomTextInput(originalSelect)),optionLabel.appendChild(optionCheckbox),optionLabel.appendChild(optionLabelText),optionItem.appendChild(optionLabel),nestedOptionsList.appendChild(optionItem)}optgroupItem.appendChild(nestedOptionsList),nestedList.appendChild(optgroupItem)}else{const options=originalSelect.getElementsByTagName("option");for(let j=0;j<options.length;j++){const option=options[j],optionItem=document.createElement("div");optionItem.classList.add("tail--nested-dropdown-item");const optionCheckbox=document.createElement("input");optionCheckbox.type="checkbox",optionCheckbox.value=option.textContent;const optionLabel=document.createElement("label"),optionLabelText=document.createElement("span");optionLabelText.textContent=option.textContent,option.dataset.description&&(optionLabelText.innerHTML+=`<small>${option.dataset.description}</small>`),option.selected&&option.hasAttribute("selected")&&(optionCheckbox.checked=!0,updateCounter(originalSelect),updateCustomTextInput(originalSelect)),optionLabel.appendChild(optionCheckbox),optionLabel.appendChild(optionLabelText),optionItem.appendChild(optionLabel),nestedList.appendChild(optionItem)}}customDropdown.setAttribute("role","combobox"),customDropdown.setAttribute("aria-haspopup","true"),customDropdown.setAttribute("aria-expanded","false"),attachOptionCheckboxListeners(),nestedList.appendChild(fragment)}function toggleAll(originalSelect,toggleAllCheckbox){const isChecked=toggleAllCheckbox.checked,optionCheckboxes=nestedList.querySelectorAll('input[type="checkbox"]');optionCheckboxes.forEach(checkbox=>{checkbox.checked=isChecked,updateOriginalOptionState(originalSelect,checkbox)})}function uncheckAll(originalSelect){const optionCheckboxes=nestedList.querySelectorAll('input[type="checkbox"]');optionCheckboxes.forEach(checkbox=>{checkbox.checked=!1,updateOriginalOptionState(originalSelect,checkbox)});const originalOptions=originalSelect.getElementsByTagName("option");for(let i=0;i<originalOptions.length;i++)originalOptions[i].selected=!1}function toggleOption(checkbox){if(originalSelect.multiple)updateOriginalOptionState(originalSelect,checkbox);else{const optionCheckboxes=nestedList.querySelectorAll('.tail--nested-dropdown-item input[type="checkbox"]');optionCheckboxes.forEach(cb=>cb.checked=!1),checkbox.checked=!0,updateOriginalOptionState(originalSelect,checkbox)}}function toggleOptgroup(optgroupCheckbox){const isChecked=optgroupCheckbox.checked,nestedOptionsList=optgroupCheckbox.closest(".tail--optgroup").querySelector(".tail--nested-dropdown-list"),optionCheckboxes=nestedOptionsList.querySelectorAll('input[type="checkbox"]');if(optionCheckboxes.forEach(checkbox=>{checkbox.checked=isChecked,toggleOption(checkbox)}),!originalSelect.multiple){const customDropdown=originalSelect.closest(".tail-select");if(customDropdown){const otherOptgroupCheckboxes=customDropdown.querySelectorAll('.tail--nested-dropdown-item input[type="checkbox"]');otherOptgroupCheckboxes.forEach(cb=>{cb!==optgroupCheckbox&&(cb.checked=!1,updateOriginalOptionState(originalSelect,cb))})}}updateOriginalOptionState(originalSelect,optgroupCheckbox)}function attachOptionCheckboxListeners(){const optionCheckboxes=nestedList.querySelectorAll('.tail--nested-dropdown-item input[type="checkbox"]');optionCheckboxes.forEach(checkbox=>{checkbox.addEventListener("change",()=>toggleOption(checkbox))})}function updateOriginalOptionState(originalSelect,checkbox,customDropdown){const optionValue=checkbox.value,option=Array.from(originalSelect.options).find(opt=>opt.value===optionValue||opt.textContent===optionValue);if(option){checkbox.checked?option.selected=!0:option.selected=!1;const event=new Event("change",{bubbles:!0});originalSelect.dispatchEvent(event)}const selectedOptions=Array.from(originalSelect.options).filter(opt=>opt.selected);originalSelect.multiple?searchInput.value=selectedOptions.map(opt=>opt.textContent).join(", "):selectedOptions.length>0&&searchInput?searchInput.value=selectedOptions[0].textContent:searchInput.value="",opts.multiTags&&originalSelect.multiple&&updateSelectedOptionsList(selectedOptionsList,selectedOptions);const selectedValues=selectedOptions.map(opt=>opt.value);for(var options=originalSelect.options,count=0,i=0;i<options.length;i++)options[i].selected&&count++;if(opts.multiCounter){let customId=originalSelect.id;if(customId){let counterElement=document.querySelector(`.${customId}`).querySelector(".tail--counter");counterElement&&(counterElement.textContent=count)}}}function filterOptions(originalSelect,searchInput){const searchTerm=searchInput.value.trim().toLowerCase(),optionItems=nestedList.querySelectorAll("div");optionItems.forEach(optionItem=>{const optionCheckbox=optionItem.querySelector('input[type="checkbox"]'),optionLabel=optionCheckbox.nextElementSibling.textContent.toLowerCase(),optgroupItem=optionItem.closest("div");optionCheckbox.style.display=optionLabel.includes(searchTerm)?"inline-block":"none"}),optionItems.forEach(optionItem=>{const optionCheckbox=optionItem.querySelector('input[type="checkbox"]'),optgroupItem=optionItem.closest("div"),nestedCheckboxes=optionItem.querySelectorAll('div input[type="checkbox"]:not([style="display: none;"])'),hasVisibleNestedCheckboxes=nestedCheckboxes.length>0;optgroupItem.style.display="inline-block"===optionCheckbox.style.display||hasVisibleNestedCheckboxes?"block":"none"})}function updateSelectedOptionsList(selectedOptionsList,selectedOptions){selectedOptionsList.innerHTML="",selectedOptions.forEach(opt=>{const listItem=document.createElement("li");listItem.textContent=opt.textContent,selectedOptionsList.appendChild(listItem)})}function updateCustomTextInput(originalSelect){const selectedOptions=Array.from(originalSelect.options).filter(opt=>opt.selected&&opt.hasAttribute("selected"));originalSelect.multiple?searchInput.value=selectedOptions.map(opt=>opt.textContent).join(", "):selectedOptions.length>0&&searchInput?searchInput.value=selectedOptions[0].textContent:searchInput.value="",opts.multiTags&&originalSelect.multiple&&updateSelectedOptionsList(selectedOptionsList,selectedOptions)}function updateCounter(originalSelect){let customId=originalSelect.id;if(customId){let counterElement=document.querySelector(`.${customId}`).querySelector(".tail--counter");if(counterElement){const count=Array.from(originalSelect.options).filter(opt=>opt.selected).length;counterElement.textContent=count}}}function toggleDropdownVisibility(){nestedList.style.display="block",customDropdown.setAttribute("aria-expanded","true")}function hideDropdown(){nestedList.style.display="none",customDropdown.setAttribute("aria-expanded","false")}function handleClickOutside(event){customDropdown.contains(event.target)||hideDropdown()}function handleKeyDown(event){"Escape"===event.key&&hideDropdown()}selectedOptionsList.classList.add("tail--selected-options-list"),opts.multiTags&&originalSelect.multiple&&customDropdown.insertAdjacentElement("afterend",selectedOptionsList),searchInput.addEventListener("focus",toggleDropdownVisibility),document.addEventListener("click",handleClickOutside),document.addEventListener("keydown",handleKeyDown),buildNestedList()})}};
|