{"id":17381754,"url":"https://github.com/PhilippeMarcMeyer/vanillaSelectBox","last_synced_at":"2025-02-27T10:30:27.586Z","repository":{"id":37094189,"uuid":"207275282","full_name":"PhilippeMarcMeyer/vanillaSelectBox","owner":"PhilippeMarcMeyer","description":"A dropdown menu with lots of features that takes a select tag and transforms it into a single or multi-select menu with 1 or 2 levels","archived":false,"fork":false,"pushed_at":"2023-05-12T06:32:17.000Z","size":343,"stargazers_count":129,"open_issues_count":16,"forks_count":50,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-09-19T05:49:48.305Z","etag":null,"topics":["checkbox","dropdown","help-wanted","javascript","selectbox","vanilla-javascript","vanilla-js"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PhilippeMarcMeyer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-09T09:38:57.000Z","updated_at":"2024-08-30T13:14:42.000Z","dependencies_parsed_at":"2023-01-30T06:46:23.303Z","dependency_job_id":null,"html_url":"https://github.com/PhilippeMarcMeyer/vanillaSelectBox","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilippeMarcMeyer%2FvanillaSelectBox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilippeMarcMeyer%2FvanillaSelectBox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilippeMarcMeyer%2FvanillaSelectBox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilippeMarcMeyer%2FvanillaSelectBox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PhilippeMarcMeyer","download_url":"https://codeload.github.com/PhilippeMarcMeyer/vanillaSelectBox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219842817,"owners_count":16556563,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["checkbox","dropdown","help-wanted","javascript","selectbox","vanilla-javascript","vanilla-js"],"created_at":"2024-10-16T07:01:36.949Z","updated_at":"2024-10-16T07:04:45.027Z","avatar_url":"https://github.com/PhilippeMarcMeyer.png","language":"JavaScript","funding_links":[],"categories":["UI Components","JavaScript"],"sub_categories":["Dropdown"],"readme":"\n# vanillaSelectBox v1.0.5\n\nnpm i vanillaselectbox\n\n## vanillaSelectBox : v1.05 : setValue() bug correction on single mode. You could not set the value\nif you select all the elements when the list is filtered by the textBox it will put the value All to the placeholder even when it does not have all the values selected, if you close and open again the select you will notice that not all the values are checked and the placeholder says All\n\n## New : Possibility to change the dropdown tree and change the remote search function\n\n### A nice select/multiselect ui with no dependency and two levels support thru optgroups\n\nThe idea is to use a mundane SELECT element, hide it and provide a nice drop-down instead. But the data comes from the original element and this one is updated with choices made and still receives a change event. An exception is the remote init() and the remote search() functions (optional) added with v 0.75 but they require at least an empty SELECT element and the result is still provided in the original element. Feel free to ask more explanations in the discussions tab. See you soon\n\n### New : you can use the discussions page to help me improve this little tool or even suggest other plugins\n\n### vanillaSelectBox is not currently in v1+, please test it carefully before using it in production (interactions with other plugins, css) and be kind enough to report any bug to me so I can improve it. \n\n\n#### Find examples at the end of the readme file !\n\n#### Check my todo list at the very bottom !\n\n![screen shot](https://raw.githubusercontent.com/PhilippeMarcMeyer/vanillaSelectBox/master/vanillaSelectBox.png)\n\nDemo classic : https://philippemarcmeyer.github.io/vanillaSelectBox/index.html?v=1.05\n\nDemo remote  : https://philippemarcmeyer.github.io/vanillaSelectBox/ajaxDemo.html?v=1.05\n\n### Transform an HTML select into a selectBox dropdown\n#### the select is hidden and the chosen value(s) is/are available in the source select\n\n```\nlet selectBox = new vanillaSelectBox(\"#brands\",{\"maxHeight\":200,search:true});\n```\n* param 1 : css selector of a normal select element\n* param 2 : options \n\n### Available options : \n* maxWidth : for the UI if you don't want the title to expand to much to the right\n* minWidth : for the UI if you don't want the title to be to narrow (combining both, you've got a fixed width)\n* maxHeight : the maxHeight set a scroll on the menu when there are too many items \n* translations : { \"all\": \"Tous\", \"item\":\"élément\",\"items\": \"éléments\",\"selectAll\":\"Tout sélectionner\",\"clearAll\":\"Effacer\"}\n* search : true/false, to provide a search input text to reduce the list\n* placeHolder : well that's a placeholder !\n* stayOpen : true/false. defaut is false : that's a drop-down. Set it to true and that\"s a list (\u003e= v 0.25)\n* disableSelectAll : true/false. defaut is false : add a checkbox select all / clear all\n* maxSelect : integer. set a maximum in the number of selectable options. CheckAll/uncheckAll is then disabled\n* maxOptionWidth : integer,set a maximum width for each option for narrow menus\n* itemsSeparator : string, to change the default \",\" item separator showing in the button\n\n### New options : Remote \n* remote : \n  \"remote\": { //object =\u003e the search input searches remote thanks to the user defined handler onSearch\n\t\"onInit\": getData,// no function here make init comes from SELECT element\n\t\"onInitSize\": 8,//  limits the number of data lines for init\n\t\"onSearch\": getData // no function here make search local\n}\n\n### Automatic options :\n* single or multiple choices : depends on the \"multiple\" attribute that you put in the select code \n* size : if you set a multiple attribute and a size attribute in the select (for instance 3) :\n  * the title zone will enumerate the chosen values as a comma separated string until it reaches \"size\"\n  * Above it will show \"x items\" or \"x\" + whatever you put in the translations.items key\n  * If all the items are selected, it will show \"all\" or whatever you put in the translations.items all\n\n```\n\u003cselect id=\"brands\" multiple size=\"3\"\u003e\n```\n#### Result :\n\n![screen shot](https://raw.githubusercontent.com/PhilippeMarcMeyer/vanillaSelectBox/master/sizeMatters.png)\n\n\n### Available commands :\n* empty()\n* setValue([] || '' || 'all') =\u003e the multiple uses an array of values or a comma separated string or the string 'all'\n* disable()\n* enable()\n* destroy()\n* enableItems([] || '') =\u003e array of values or comma delimited list\n* disableItems([] || '') =\u003e array of values or comma delimited list\n```\nselectBox = new vanillaSelectBox(\"#brandsOne\", { \"maxHeight\": 200, \"search\": true, \"placeHolder\": \"Choose a brand...\" });\nselectBox.disableItems(['Lamborghini','Land Rover']);\n```\n\n#### History : \n\nv1.05 : setValue() bug correction on single mode. You could not set the value\n\nv1.04 : select all issue fixed by https://github.com/arthur911016 \n\nv1.03 : getResult() an new fonction to get the selected values in an array\n\nv1.02 : Adding 2 new options \"itemsSeparator\" to change the default \",\" item separator showing in the button and translations.item to show the item in singular if there is only one.\n\nv1.01 : Removing useless code line 550,551 issue 71 by chchch\n\nv1.00 : Due to demand : added a package.json file and switched to 1.0.0 in preparation to an upload to npm\n\nv0.78 : Stop using inline styles in the main button. You can steal use keepInlineStyles:true to use the legacy behaviour\n\nv0.77 : Work on place holder with bastoune help =\u003e still seems to lose placeholder value on multiple dropdown checkall\n\nv0.76 : Possibility to change the dropdown tree and change the remote search function + correcting empty() function\n\nv0.75 : Remote search ready + local search modification : when a check on optgroup checks children only \n        if they not excluded from search.\n\nv0.72 : Remote search (WIP) bugfix [x] Select all duplicated\n\nv0.71 : Remote search (WIP) better code =\u003e the remote search user deined function must return a promise\n\nv0.70 : remote search (WIP) can be tested. works only on 1 level menus (not optgroups)\n\nv0.65 : Two levels: bug fix : groups are checked/unchecked when check all/uncheck all is clicked\n\nv0.64 : Two levels: groups are now checkable to check/uncheck the children options \n\nv0.63 : Two levels: one click on the group selects / unselects children\n\nv0.62 : New option: maxOptionWidth set a maximum width for each option for narrow menus (ellipsis troncature)\n\nv0.61 : New option: maxSelect, set a maximum to the selectable options in a multiple choice menu\n\nv0.60 : Two levels: optgroups are now used to show two level dropdowns \n\n ![screen shot](https://raw.githubusercontent.com/PhilippeMarcMeyer/vanillaSelectBox/master/twoLevels.jpg)\n\nv0.59 : Bug fix : search box was overlapping first item in single selects\n\nv0.58 : Bug fixes\n\nv0.57 : Bug fix (minWidth option not honored)\n\nv0.56 : The multiselect checkboxes are a little smaller, maxWidth option is now working + added minWidth option as well\n        The button has now a style attribute to protect its appearance \n\nv0.55 : All attributes from the original select options are copied to the selectBox element.\n        Excepted =\u003e \"selected\",\"disabled\",\"data-text\",\"data-value\",\"style\"\n        \nv0.54 : if all the options of the select are selected by the user then the check all checkbox is checked.\n\nv0.53 : if all the options of the select are selected then the check all checkbox is checked =\u003e see demo \"select all test\"\n\nv0.52 : Better support of select('all') =\u003e command is consistent with checkbox and selecting / deselecting while searching select / uncheck only the found items\n\nv0.51 : Translations for select all/clear all + minor css corrections + don't select disabled items\n\nv0.50 : PR by https://github.com/jaguerra2017 adding a select all/clear all check button + optgroup support !\n\nv 0.41 : Bug corrected, the menu content was misplaced if a css transform was applied on a parent\n\nv 0.40 : A click on one selectBox close the other opened boxes\n\nv 0.35 : You can enable and disable items. The already disble options of the select are also used at init time.\n\nv 0.30 : The menu stops moving around on window resize and scroll + z-index in order of creation for multiple instances\n\nv 0.26 : Corrected bug in stayOpen mode with disable() function\n\nv 0.25 : New option stayOpen, and the dropbox is no longer a dropbox but a nice multi-select\n \n ![screen shot](https://raw.githubusercontent.com/PhilippeMarcMeyer/vanillaSelectBox/master/stayOpen.jpg)\n \nv 0.22 : Migrating the function to vanillaSelectBox prototype =\u003e several instances of vanillaSelectBox() but 1 set of functions in memory\n \nv 0.21 : IE 11 compatibility\n\nv 0.20 : working selectBox both single and multiple choices, with search-box !\n\nv 0.10 : functional plugin for both single and multiple selects, without search box for the moment\n\nv 0.02 : added dispatch change event to select + nicer check mark\n\nv 0.01 : first commit =\u003e basics for a single select box + the Dom is cleaned if you init twice\n\n## Examples\n\nSingle select menu :\n\n```\n       \u003cselect id=\"singleTest\"\u003e\n            \u003coption value=\"Abarth\" \u003eAbarth\u003c/option\u003e\n            \u003coption value=\"Alfa Romeo\"\u003eAlfa Romeo\u003c/option\u003e\n            \u003coption value=\"Alpine\"\u003eAlpine\u003c/option\u003e\n            \u003coption value=\"Aston Martin\" \u003eAston Martin\u003c/option\u003e\n            \u003coption value=\"Audi\" \u003eAudi\u003c/option\u003e\n            \u003coption value=\"Bentley\" \u003eBentley\u003c/option\u003e\n            \u003coption value=\"BMW\" \u003eBMW\u003c/option\u003e\n            \u003coption value=\"Cadillac\"\u003eCadillac\u003c/option\u003e\n            \u003coption value=\"Chevrolet\"\u003eChevrolet\u003c/option\u003e\n            \u003coption value=\"Citroën\"\u003eCitroën\u003c/option\u003e\n            \u003coption value=\"Cupra\"\u003eCupra\u003c/option\u003e\n            \u003coption value=\"DACIA\"\u003eDacia\u003c/option\u003e\n        \u003c/select\u003e\n\t\nlet selectCars = new vanillaSelectBox(\n\t\"#singleTest\",\n\t    {\n\t    \t\"placeHolder\":\"Choose your car\",\n\t\ttranslations: { \"all\": \"All\", \"items\": \"Cars\" } \n\t    });\n\n```\nMultiple select menu :\nnote the \"multiple\" attribute to ge en multiple select menu\nand the size=\"2\" to replace the comma delimited string of selected items by \"3 items\" where more than size items are selected\n(here items is translated to Cars)\n```\n       \u003cselect id=\"multiTest\" multiple size=\"2\"\u003e\n            \u003coption value=\"Abarth\" \u003eAbarth\u003c/option\u003e\n            \u003coption value=\"Alfa Romeo\"\u003eAlfa Romeo\u003c/option\u003e\n            \u003coption value=\"Alpine\"\u003eAlpine\u003c/option\u003e\n            \u003coption value=\"Aston Martin\" \u003eAston Martin\u003c/option\u003e\n            \u003coption value=\"Audi\" \u003eAudi\u003c/option\u003e\n            \u003coption value=\"Bentley\" \u003eBentley\u003c/option\u003e\n            \u003coption value=\"BMW\" \u003eBMW\u003c/option\u003e\n            \u003coption value=\"Cadillac\"\u003eCadillac\u003c/option\u003e\n            \u003coption value=\"Chevrolet\"\u003eChevrolet\u003c/option\u003e\n            \u003coption value=\"Citroën\"\u003eCitroën\u003c/option\u003e\n            \u003coption value=\"Cupra\"\u003eCupra\u003c/option\u003e\n            \u003coption value=\"DACIA\"\u003eDacia\u003c/option\u003e\n        \u003c/select\u003e\n\t\nlet selectCars = new vanillaSelectBox(\n\t\"#multiTest\",\n\t    {\n\t\t\"placeHolder\":\"Choose up to 3 cars\",\n\t\t\"maxSelect\":3,\n\t\t\"translations\": { \"all\": \"All\", \"items\": \"Cars\" } \n\t    });\n\n```\n\nTwo levels : just use optgroup tags to make it two levels\n\n```\n        \u003cdiv\u003e \n            \u003clabel for=\"dino-select\"\u003eChoose dinosaurs :\u003c/label\u003e\n            \u003cselect id=\"dino-select\" multiple size=\"3\" \u003e\n                \u003coptgroup label=\"Theropods\"\u003e\n                    \u003coption\u003eTyrannosaurus\u003c/option\u003e\n                    \u003coption\u003eVelociraptor\u003c/option\u003e\n                    \u003coption\u003eDeinonychus\u003c/option\u003e\n                \u003c/optgroup\u003e\n                \u003coptgroup label=\"Sauropods\"\u003e\n                    \u003coption\u003eDiplodocus\u003c/option\u003e\n                    \u003coption\u003eSaltasaurus\u003c/option\u003e\n                    \u003coption\u003eApatosaurus\u003c/option\u003e\n                \u003c/optgroup\u003e\n            \u003c/select\u003e\n        \u003c/div\u003e\n        \n\u003cscript\u003e\n            \n// How to get the result from the original select tag :\n            \nlet chosenDinos = [];\n\nfunction getValues(id) {\nlet result = [];\nlet collection = document.querySelectorAll(\"#\" + id + \" option\");\ncollection.forEach(function (x) {\n\tif (x.selected) {\n\t\tresult.push(x.value);\n\t}\n});\nreturn result;\n}\n\nlet selectDinos = new vanillaSelectBox(\"#dino-select\",\n    {\"maxHeight\": 300,\n    \"search\": true,\n    translations: { \"all\": \"All\", \"items\": \"Dinos\" } \n    });\n\ndocument.getElementById(\"dino-select\").addEventListener(\"change\", function (e) {\n\tchosenDinos = getValues(\"dino-select\");\n\tconsole.log(chosenDinos);\n});\n      \n\u003c/script\u003e\n        \n\n```\n\nmaxSelect option : limits the number of options you can select\n\n```\nlet selectCars = new vanillaSelectBox(\"#demoShort\",\n    {\"maxSelect\": 4, \n    \"maxHeight\": 200,\n    \"search\": true,\n    translations: { \"all\": \"All\", \"items\": \"Cars\" } \n    });\n```\n\n\nmaxOptionWidth option : limits the width of the menu options to make the menu more narrow using ellipis\n\n```\nlet selectCars = new vanillaSelectBox(\"#demoShort\",\n    {\"maxOptionWidth\":70,\n    \"maxHeight\": 200,\n    \"search\": true,\n    translations: { \"all\": \"All\", \"items\": \"Cars\" } \n});\n```\n\nRemote search example :\n\n```\n\u003cselect id=\"demoM1\" multiple=\"true\" size=\"3\"\u003e\n\u003c/select\u003e\n\nlet selectDemoM1 = new vanillaSelectBox(\"#demoM1\",\n    {\n        \"maxHeight\": 300,\n        \"search\": true,\n        \"placeHolder\" : \"search to load more data\",\n        \"translations\": { \"all\": \"everybody\", \"items\": \"people\" },\n        \"remote\": {\n            \"onSearch\": doSearch, // used fro search and init\n            \"onInitSize\": 10, // if \u003e 0 onSearch is used for init to populate le select element with the {onInitSize} first elements\n        }\n    }\n);\n\nfunction doSearch(what, datasize) {\n      let valueProperty = \"id\";\n      let textProperty = \"name\";\n      return new Promise(function (resolve, reject) {\n          var xhr = new XMLHttpRequest();\n          xhr.overrideMimeType(\"application/json\");\n          xhr.open('GET','./data.json', true);\n          xhr.onload = function () {\n              if (this.status \u003e= 200 \u0026\u0026 this.status \u003c 300) {\n                  var data = JSON.parse(xhr.response);\n\n                  if (what == \"\" \u0026\u0026 datasize != undefined \u0026\u0026 datasize \u003e 0) { // for init to show some data\n                      data = data.slice(0, datasize);\n                      data = data.map(function (x) {\n                          return {\n                              value: x[valueProperty],\n                              text: x[textProperty]\n                          }\n                      });\n                  } else {\n                      data = data.filter(function (x) {\n                          let name = x[textProperty].toLowerCase();\n                          if (name.indexOf(what.toLowerCase()) != -1)\n                              return {\n                                  value: x[valueProperty],\n                                  text: x[textProperty]\n                              }\n                      });\n                  }\n                  resolve(data);\n              } else {\n                  reject({\n                      status: this.status,\n                      statusText: xhr.statusText\n                  });\n              }\n          };\n          xhr.onerror = function () {\n              reject({\n                  status: this.status,\n                  statusText: xhr.statusText\n              });\n          };\n          xhr.send();\n      });\n  }\n\n```\n\n### TODO\n\n- ~~Remote search and loading : manage 2 levels dropdowns~~ DONE in 0.75\n- Add a getResult() function instead of just getting it from the DOM hidden select element\n- ~~Add more than levels via optgroups~~ NO don't over complicate this plugin, make another\n- ~~Maybe keep the tree internaly as an objet and keeping the original select as an option but not mandatory anymore~~ NO the select element is the main idea of this plugin\n- Better alternate css support =\u003e first of all change css icons with images\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPhilippeMarcMeyer%2FvanillaSelectBox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPhilippeMarcMeyer%2FvanillaSelectBox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPhilippeMarcMeyer%2FvanillaSelectBox/lists"}