diff --git a/README.md b/README.md index 6dd7b3b..d19c208 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ $('select').bsSelect('method', param); | `'selectFirst'` | `$('select').bsSelect('selectFirst');` | Selects the first option element | | `'selectLast'` | `$('select').bsSelect('selectLast');` | Selects the last option element | | `'selectNone'` | `$('select').bsSelect('selectNone');` | deselects all values | +| `'clear'` | `$('select').bsSelect('clear');` | Empties the Select | | `'updateOptions'` | `$('select').bsSelect('updateOptions', {buttonClass: 'btn btn-danger',...});` | Changes the settings of the dropdown. | | `'setBtnClass'` | `$('select').bsSelect('setBtnClass', 'btn btn-danger');` | Behaves like `updateOptions`. The btnClass option is overwritten. | | `'refresh'` | `$('select').bsSelect('refresh');` | Rebuild the dropdown. This is useful if the options are changed via Javascript. | @@ -163,6 +164,7 @@ $('select').bsSelect('method', param); | shown.bs.select | Fired when the dropdown has been made visible to the user and CSS transitions have completed. | | refresh.bs.select | Fires when the `refresh` method has been invoked. | | change.bs.select | Fires when the method `val` has been called. Additional parameters are [valueBefore, valueAfter] | +| clear.bs.select | Fires when the `clear` method has been called. | | acceptChange.bs.select | If the function onBeforeChange returns true, this event is fired. | | cancelChange.bs.select | If the function onBeforeChange returns false, this event is fired. | | update.bs.select | Fires when the method `updateOptions` or `setBtnClass` was called. | diff --git a/composer.json b/composer.json index 1c74c4d..bbf9db8 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "webcito/bs-select", - "version": "2.1.10", + "version": "2.1.11", "description": "A jQuery-based plugin for creating customizable Bootstrap-style select dropdowns with various features including search, multi-select, and dynamic updates.", "minimum-stability": "stable", "license": "MIT", diff --git a/dist/jquery.bs-select.js b/dist/jquery.bs-select.js index 2488127..304ab12 100644 --- a/dist/jquery.bs-select.js +++ b/dist/jquery.bs-select.js @@ -1119,6 +1119,13 @@ } } break; + case 'clear': { + $select.val(null); + $select.find('option,optgroup').remove(); + refresh($select); + trigger($select, 'clear.bs.select'); + } + break; case 'selectLast': { if (onBeforeChange($select)) { $select.val(null); diff --git a/dist/jquery.bs-select.min.js b/dist/jquery.bs-select.min.js index 62fc72a..00d1325 100644 --- a/dist/jquery.bs-select.min.js +++ b/dist/jquery.bs-select.min.js @@ -1 +1 @@ -(function($){const defaultTranslations={btnEmptyText:"Please select..",deselectAllText:"Deselect All",selectAllText:"Select All",searchText:"Search..",showSelectedText:function(count,total){return count+" of "+total+" selected"}};const translations=window.bsSelectTranslations||defaultTranslations;const WRAPPER_CLASS="js-bs-select-dropdown";$.bsSelect={setDefaults:function(options){this.DEFAULTS=$.extend({},this.DEFAULTS,options||{})},getDefaults:function(){const defCopy=this.DEFAULTS;delete defCopy.debug;delete defCopy.debugElement;return defCopy},DEFAULTS:{btnWidth:"fit-content",btnEmptyText:translations.btnEmptyText,btnSplit:false,dropDirection:null,dropIconClass:"bi bi-chevron-down",menuClass:null,menuHeaderClass:"text-bg-secondary text-uppercase",btnClass:"btn-outline-dark",search:true,menuPreHtml:null,menuAppendHtml:null,menuMaxHeight:300,showSubtext:true,showActionMenu:true,showMultipleCheckboxes:false,actionMenuBtnClass:"btn-light",showSelectionAsList:false,showSelectedText:translations.showSelectedText,deselectAllText:translations.deselectAllText,selectAllText:translations.selectAllText,checkedIcon:"bi bi-check-lg",debug:false,debugElement:null,menuItemClass:null,searchText:translations.searchText,onBeforeChange:null,onKeyDown:null}};function trigger($select,event,addParams=[]){let params=[];if(event!=="any.bs.select"){trigger($select,"any.bs.select");if(addParams.length){addParams.forEach(p=>{params.push(p)})}else{params.push($select.val())}$select.trigger(event,params)}else{$select.trigger(event)}const settings=$select.data("options");if(settings.debug){console.log("trigger",event,params);if(settings.debugElement!==null){const log=$("",{class:"js-log border-bottom",html:"["+(new Date).toUTCString()+'] trigger '+event+" fired"}).prependTo(settings.debugElement);setTimeout(function(){log.remove()},5e3)}}}function getDropDown($select){return $select.closest(`.${WRAPPER_CLASS}`)}function show($select){const $dropdown=getDropDown($select);if($dropdown.length){$dropdown.dropdown("show")}}function hide($select){const $dropdown=getDropDown($select);if($dropdown.length){$dropdown.dropdown("hide")}}function getSelectedValuesFromDropdown($select){const $dropdown=getDropDown($select);const multiple=$select.prop("multiple");let values=[];$dropdown.find(".dropdown-item:not(.active)").find(".dropdown-item-select-icon").hide();$dropdown.find(".dropdown-item.active").each(function(i,element){let val=$select.find("option:eq("+$(element).data("index")+")").prop("value");if(val!==false){values.push(val);$(element).find(".dropdown-item-select-icon").show()}});if(multiple){return values}else if(!isValueEmpty(values)){return values[0]}else{return null}}function setSelectValues($select){const settings=$select.data("options");if(settings.debug){console.log("bsSelect:setSelectValues",$select.val())}const multiple=$select.prop("multiple");let values=getSelectedValuesFromDropdown($select);$select.val(values)}function toggleAllItemsState($select,state=false){const dropdown=getDropDown($select);const beforeValues=$select.val();const options=$select.find("option");const settings=$select.data("options");const multiple=false!==$select.prop("multiple");options.prop("selected",state);const toggleCheckIcon=multiple&&settings.showMultipleCheckboxes;options.each(function(i){const $item=dropdown.find('.dropdown-item[data-index="'+i+'"]');if(state){$item.addClass("active");$item.find(".dropdown-item-select-icon").show()}else{$item.removeClass("active");$item.find(".dropdown-item-select-icon").hide()}});if(toggleCheckIcon){dropdown.find(".dropdown-item:not(.active) .js-icon-checklist.bi-check-square").removeClass("bi-check-square").addClass("bi-square");dropdown.find(".dropdown-item.active .js-icon-checklist.bi-square").removeClass("bi-square").addClass("bi-check-square")}setSelectValues($select);setDropdownTitle($select);const ev=state?"selectAll":"selectNone";trigger($select,ev+".bs.select");const afterValues=getSelectedValuesFromDropdown($select);trigger($select,"change.bs.select",[beforeValues,afterValues])}function getBootstrapMajorVersion(){if(typeof $.fn.modal==="undefined"||typeof $.fn.modal.Constructor==="undefined"){console.error("Bootstrap Modal Plugin ist nicht verfügbar");return}const bootstrapVersion=$.fn.modal.Constructor.VERSION;return parseInt(bootstrapVersion.split(".")[0])}function setupDropdown($dropdown,selectElement,multiple){const $dropdownToggle=$dropdown.find(".dropdown-toggle");const autoclose=$dropdownToggle.data("autoClose")||$dropdownToggle.data("bsAutoClose")||"true";const BS_V=getBootstrapMajorVersion();$dropdown.on("click",".js-select-select-all",function(e){e.preventDefault();if(onBeforeChange(selectElement)){toggleAllItemsState(selectElement,true);if(BS_V===4&&multiple&&(autoclose==="true"||autoclose==="outside")){e.stopPropagation()}}}).on("click",".js-select-select-none",function(e){e.preventDefault();if(onBeforeChange(selectElement)){toggleAllItemsState(selectElement,false);if(BS_V===4&&multiple&&(autoclose==="true"||autoclose==="outside")){e.stopPropagation()}}}).on("hidden.bs.dropdown",function(){let searchField=$(this).find('[type="search"]');if(searchField.length){const searchElements=$dropdown.find("[data-index]");searchElements.removeClass("d-none").addClass("d-flex");searchField.val(null).trigger("keyup")}}).on("keyup input",'[type="search"]',function(e){const settings=selectElement.data("options");const searchField=$(e.currentTarget);const searchPattern=searchField.val().trim();if(settings.debug){console.log("bsSelect:search",searchPattern)}const searchElements=$dropdown.find("[data-index]");const dropdownHeaders=$dropdown.find(".dropdown-header");searchElements.removeClass("d-none").addClass("d-flex");dropdownHeaders.removeClass("d-none");if(settings.debug){console.log("bsSelect:search elements:",searchElements.length)}if(!isValueEmpty(searchPattern)){const search=searchPattern.toUpperCase();searchElements.each(function(index,value){let currentName=$(value).text().trim();if(currentName.toUpperCase().indexOf(search)>-1){if(settings.debug){console.log("bsSelect:search elements found:",currentName)}$(value).removeClass("d-none").addClass("d-flex")}else{if(settings.debug){console.log("bsSelect:search elements not found:",currentName)}$(value).addClass("d-none").removeClass("d-flex")}});dropdownHeaders.addClass("d-none")}else{if(settings.debug){console.log("bsSelect:search is empty")}searchElements.removeClass("d-none");dropdownHeaders.removeClass("d-none")}}).on("click",'[data-dismiss="dropdown"], [data-bs-dismiss="dropdown"]',function(e){const btn=$(e.currentTarget);const dd=btn.closest("."+WRAPPER_CLASS);dd.find('[data-bs-toggle="dropdown"],[data-toggle="dropdown"]').dropdown("hide")}).on("click",".dropdown-item",function(e){e.preventDefault();const settings=selectElement.data("options");const active=$(e.currentTarget).hasClass("active");const beforeValues=selectElement.val();if(onBeforeChange(selectElement)){const item=$(e.currentTarget);if(!multiple){$dropdown.find(".dropdown-item.active").not(item).removeClass("active")}item.toggleClass("active");const toggleCheckIcon=multiple&&settings.showMultipleCheckboxes;if(active){if(toggleCheckIcon){item.find(".js-icon-checklist").removeClass("bi-square").addClass("bi-check-square")}item.find(".dropdown-item-select-icon").show()}else{if(toggleCheckIcon){item.find(".js-icon-checklist").removeClass("bi-check-square").addClass("bi-square")}item.find(".dropdown-item-select-icon").hide()}setSelectValues(selectElement);const afterValues=getSelectedValuesFromDropdown(selectElement);setDropdownTitle(selectElement);trigger(selectElement,"change.bs.select",[beforeValues,afterValues]);if(BS_V===4&&multiple&&(autoclose==="true"||autoclose==="outside")){e.stopPropagation()}}}).on("keydown",function(e){const $wrap=$(e.currentTarget);const $selectElement=$wrap.find("select");const settings=$selectElement.data("options");if(typeof settings.onKeyDown==="function"){settings.onKeyDown($selectElement,e)}trigger($selectElement,"keydown.bs.select",[$selectElement,e])}).on("keydown",'[type="search"]',function(e){switch(e.code){case"Enter":e.preventDefault();const item=$dropdown.find(".dropdown-item:visible:first");if(item.length){item.trigger("click");$dropdown.removeClass("show");$dropdown.find(".dropdown-menu").removeClass("show")}break;default:}}).on("hide.bs.dropdown",function(){const $select=$dropdown.find("select");const valueBefore=$select.data("valueBefore");const currentValue=$select.val();const valueChanged=hasValueChanged(valueBefore,currentValue);trigger($select,"hide.bs.select",[valueChanged])}).on("hidden.bs.dropdown",function(){const $select=$dropdown.find("select");$select.removeData("valueBefore");trigger($select,"hidden.bs.select")}).on("show.bs.dropdown",function(){const $select=$dropdown.find("select");$select.data("valueBefore",$select.val());trigger($select,"show.bs.select")}).on("shown.bs.dropdown",function(){const $select=$dropdown.find("select");trigger($select,"shown.bs.select");const searchElement=$dropdown.find('[type="search"]');if(searchElement.length){searchElement.focus()}})}function arraysEqual(arr1,arr2){if(arr1.length!==arr2.length){return false}const sortedArr1=[...arr1].sort();const sortedArr2=[...arr2].sort();for(let i=0;i",{class:`${WRAPPER_CLASS} position-relative`,css:{width:settings.btnWidth}}).insertAfter($select);if(settings.dropDirection!==null){$dropdown.addClass(settings.dropDirection)}const toggleIconClass=settings.dropIconClass===null?"dropdown-toggle":"";const dropIcon=settings.dropIconClass!==null?``:"";if(!settings.btnSplit){$("