Coder Social home page Coder Social logo

philippemarcmeyer / vanillaselectbox Goto Github PK

View Code? Open in Web Editor NEW
129.0 6.0 50.0 343 KB

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

License: MIT License

HTML 43.83% CSS 4.22% JavaScript 51.95%
javascript dropdown vanilla-javascript vanilla-js help-wanted selectbox checkbox

vanillaselectbox's Issues

Change event is dispatched on the page load

When the select box is initially generated, the privateSendChange function is called. Is this intentional? Shouldn't the change event be emitted only for changes coming from a user?

The culprit line was added in this commit. That commit was later (partially) reverted, but the culprit line stayed there. This makes me more suspicious about it.

In my application, I'm listening for user change events and it causes small inconvenience when this event is triggered on the page load.

Inline Button styles

First of all. Hats off to you Sir. This plugin is awesome. Does the job well.

When using the plugin I faced 2 issues.

  1. Inline styling on the button('.vsb-main button') and caret icon
  2. cant initialize multiple instances of the selectBox using class names.

Solution for 1
I went through the documentation and found a prop that could help "keepInlineStyles". But when I added the prop it did nothing. So I inspected the code and found that this prop was not implemented or may be removed.

I am submitting a pull request with this prop added in along with another prop I added called "keepInlineCaretStyles" to remove the inline styles on the caret

I feel this could do the minimum job to help style the select box.


this.keepInlineStyles = true;
this.keepInlineCaretStyles = true;

if(options.keepInlineStyles != undefined ) {
          this.keepInlineStyles = options.keepInlineStyles; 
}
if(options.keepInlineCaretStyles != undefined ) {
          this.keepInlineCaretStyles = options.keepInlineCaretStyles;
}

This wouldn't break the current setup as it is always set to inline styles true. Hope this could help.

Thank you.

How to make programmatically selected options visible?

Hi Philippe Marc,

First of all I really appreciate that you've created and shared this awesome project, it's exactly what I've been looking for (multiselect with search)!

As to my issue, I've gotten as far as converting my existing select/option with let selectBox = new vanillaSelectBox("#mySelectId", { ... and everything was working as expected. Using the snippet found in the README I was able to collect my selected elements and submit/save them as an array. However, the problem I'm having is that when loading the page later I'd want to populate the selectbox with the previously saved items (fetched from server with AJAX).

So I'm doing:

// savedArray = [63, 169, 178] .....
document.querySelectorAll('#mySelectId option').forEach(item => {
    if (savedArray.includes(parseInt(item.value))) {
        item.selected = true
    }
})

However, this doesn't seem to do anything, nothing gets selected. But! It still "works", in the sense that the saved items are still somehow selected "under the hood" - if I check a new item and resubmit the form the submission will contain both old and new items... so it's just the visual portion that seems to be failing.

Could you maybe poke me in the right direction? πŸ™ Is there perhaps a way to "reinitialize" the selectbox once the values have been added?

how i can use the search box for filter by groups

Hello, I am using your library and I have the following situation, I have a select that is grouped and I want to part of looking for the options, also looking for the groups, do you have any idea that can help me, thanks
image

Add a getResult() function

Hi Philippe, thanks for creating vanillaSelectBox. I'm creating an issue for the "Add a getResult() function instead of just getting it from the DOM hidden select element" in todo list. I'll start work on the issue as well.

with disabled VanillaSelectBox, clicking it submits form

When you use VanillaSelectBox in form, if you disable it and click on, form is submitted automatically, even though it shouldn't be.
[example of code to reproduce] (https://jsfiddle.net/citrusMarmelade/f7ovhzkb/)

In your code, if the VanillaSelectBox is disabled, you return directly, you only stop the propagation of the event if the VanillaSelectBox is enabled in order to trigger your own 'click' event. By default, any button is of type 'submit', would it then be possible to change the type of the button associated with the VanillaSelectBox to 'button' by default? this would solve the problem permanently.

Accessibility Issues

I'm running into a few accessibility issues when using keyboard navigation with vanillaSelectBox. A few items:

  • The individual options in the dropdown are inaccessible with keyboard navigation. I would expect to be able to open the item and use down and up arrows to navigate the options and hit enter to select an option similar to a native select input. Because a button element is used in the markup when it is focused and you hit enter, the dropdown opens (like click event) but you can't navigate to the options.
  • Because there are button elements within the vanillaSelectBox markup and because of preventDefault on the select click event, when a user tries to hit enter to submit a form in another non-vanillaSelectBox input (in my case a text input for keyword search) the form doesn't submit as expected and it fires the click event on the next vanillaSelectBox which opens up the dropdown unexpectedly.

Removing the preventDefault fixes the issue but it does submit the form when hitting enter when the vanillaSelectBox is focused. Changing the button element to a div allows for the form to submit when focused on another input. Can the button element be changed to a div to prevent these issues? Can there be some logic to make the dropdown options focusable and selectable via keyboard?

[QUESTION] How to get the actual values represented in an array?

Hey. I'm doing some client-side rendering and request handling so the form isn't submitted directly with HTML. It uses some external JavaScript (fetch) to fulfil requests. For some reason, I can't get an array of the selected options when using

const formData = new FormData(document.querySelector(`${formID}`));

and formData.entries(). It returns a string even if I selected multiple options.

Is there any way to get the actual values of the array (if multiple options are selected)?

setValue('all') gives error when using with remote feature

I am using remote feature to retrieve options contents from database and I would like to show the vanillaSelectBox with all items selected.

After creating the component, if I call setValue('all'), I receive the following error

Cannot read properties of undefined (reading 'querySelectorAll')
at vanillaSelectBox.setValue (vanillaSelectBox.js:1203:34)

Could you post an example of using setValue('all') using remote feature ?

"minWidth" option is not honored if "maxWidth" is not explicitly set

If the "minWidth" option is explicitly set, but "maxWidth" option not, "minWidth" option will not be honored.
In vanillaSelectBox.js line 84 and following (master), "maxWidth" is checked twice if it is set. The second one should probably be a check if "minWidth" is set.

Best regards

sep = ", "

Hi,

It would be nice to change all instances of sep = "," to sep = ", ", so that selected options are separated by a comma and a space. It looks a little nicer.

Or perhaps include a userOptions.separator?

self.left and self.top undefined?

In lines 558 and 559,

self.drop.style.left = self.left + "px";
self.drop.style.top = self.top + "px";

the variables self.left and self.top don't seem to be defined. Should they have some value?

How to change the fixed width?

Hi

I need change the width in multiselect checkboxes..
But, i have different sizes on my site... is there a way to allow to do this directly in the select?

Ex.
<select name="example[]" multiple size="2" style="width:250px;">

Move styling

I really like this plugin! As imporvement I would suggest moving all inline styling to the css sheet and adding/removing classes.

For example:

  • the button styling, set it in the stylsheet instead of inline (instead of the inline style use it in the style sheet, if needed with !important)
  • add a class to indicate the dropdown is visible or hidden (.vsb-menu .show for example)
  • add span for the text in the li for more styling options

Adding options to multi without using built in remote function

In my website I currently have a system to grab a list of items and put them into a selector, which works perfectly, however when converting the select element into the vanilla select box all the items disappear. What's the best way to go about adding items without using the built in JSON system?

code:

<select name="neat" id="neat" multiple></select>

<script>

          $.get("http://LINK", function( data ) {

              var splitBUs = data.split("\n")
              var list = document.getElementById('neat');

              splitBUs.forEach(function(item){
                  var option = document.createElement('option');
                  option.value = item;
                  option.innerHTML = item;
                  list.appendChild(option);
              });
          });

          let selectBox = new vanillaSelectBox("#neat",{"maxHeight":200,search:true, "placeHolder": "Subtype"});
          selectBox.setValue('all')
</script>

vanillaSelectBox does not work properly with lists that contain commas.

Discussed in #93

Originally posted by piburglar October 4, 2022
While the feature may work, technically, you cannot tell the user they have selected anything because the function setValue([] || '') does not allow/care for values that have commas in them, and therefore we cannot let the user know that they have selected anything.

How to Disable the selection of one item at a time or multiple items with a set of items while still displaying these option without them remaing selectable

Hello is there a way to disable the "selectivity" of an option while still displaying it.
My use case involves historic information via the db that show a client that they can't select an item because they have previously "made use or fulfilled that option" and hence don't need to repeat it.
However the persistent visibility of an item is a clear reminder of their account state.
Is there a specific syntax within the current functionality and it is just a matter of specifying this combination or would this require changes to the code.

Your help would be greatly appreciated.
Thank You!

Right Way to Change Options Dynamically

Hello,

Firstly, thanks for this great plugin. Works really well in most cases.

There is one problem we are stuck with, not sure if this use-case is supported. Details as follows:

  • We would like to dynamically change the options based on events that happen outside the select (for example some filtering options are chosen elsewhere, etc.)
  • We are fetching the new options using an Ajax call.
  • Since there was no explicit method defined to refresh the widget we tried to pass in the Ajax response data to the remoteSearchIntegrate function.
  • This updates the dropdown with the new data and works fine if there was no option selected before the refresh.
  • The problem is that if there is an option selected by the user it still continues to appear even though it is not part of the refreshed data (new set of options).
  • Note - We even tried to call .empty() before calling .remoteSearchIntegrate(data) - but even that did not fix the issue.

Could you please let us know if this use case is supported? If so, what is the best way to go about getting this to work?

Thanks in advance and great work once again.

setValue() is broken for single values

Trying to use setValue() with a single value only sets the selected-attribute, but doesn't add the active-class and doesn't change the displayed text.

The placeholder when all items are selected doesnt seems to work

To make this placeholder work, i had to change somes line of codes.

I wanted to make you a PR, but as I also had to change bunch of css to adapt to my app, i can't really.

Line 455
From

        if (self.multipleSize != -1) {
            if (nrActives > self.multipleSize) {
                let wordForItems = self.userOptions.translations.items || "items"
                selectedTexts = nrActives + " " + wordForItems;
            }
        }

To (i just substract 1 to make a quick fix but i could count all options but the one with 'all' as value)

        // '-1' is because the "all" option is part of self.options
        if (self.options.length - 1 == nrActives) {
            let wordForAll = self.userOptions.translations.all || "all";
            selectedTexts = wordForAll;
        } else if (self.multipleSize != -1) {
            if (nrActives > self.multipleSize) {
                let wordForItems = self.userOptions.translations.items || "items"
                selectedTexts = nrActives + " " + wordForItems;
            }
        }

Line 1207
From
nrAll++;
to

if (x.value !== 'all') {
    nrAll++;
}

setValue('all') does not properly set "select all" item.

When setValue('all') is called all items are successfully selected but the "select all" item remains.
image
When the user clicks this it does not do anything but change the text to "clear all".

Instead when setValue('all') is called it should behave the same as the user clicking the "select all" item and the "select all" item should change to "clear all".

This can be easily replicated by running selectBox2.setValue('all'); on the demo page.

Adaptive css theme

Hi,

I really like this script, it's super fast and get the job done. My only issue is about the css theme. Could it be adaptive? For example, I'm building a CRUD and using Tabler for that. I'm having a hard time to get vanillaSelectBox into the Tabler style. Is there a way around?

Cheers.

Set value for single SelectBox

Hello!
I'm using this wonderful selectbox at the moment and it seems that I cannot set value for single selectbox.

I've tried with "multiple" type select box and it works as it should.

I've looked a bit inside this function and I'm not sure but perhaps in line 1296 the condition is meant to be just - if (liVal) ?

Line above this variable is let liVal = x.getAttribute("data-value") == values;

Sorry if I'm misleading, good day!

Multiples selects

Hello,

When you have multiple selects on the same page and click on one to open it and after the second, the first one stayed opened.

Is there any way to have only one select opened at same time ?

Option to not display "all" when all items are selected

If all the items are selected, it will show "all" or whatever you put in the translations.items all

If all elements are selected i would prefer to just have the list of all selected items comma separated instead of "all" or a translation of it.

Add option for All in Multi-select

Right now when a user selects All Items in a multi-select input, it just says "All". It would be great if you could specify what that says as an option like, "All Cars". thanks for a great library!

copy attributes from original select

Would it be possible to copy all attributes from the original select options to the new one, for example. If I have added data-color="#ff0000" to an option in the original select, I would like to see that value copied to the cloned select option. It would be nice if not only data-attr would be copied but any kind of attribute in the option html.

Issue scrolling with the select box open

I noticed in #5 that you mentioned a fix on a scrolling problem, I think it's still happening, I'm using the latest 0.35 version, here's how it looks:

image

image

also checked and the .css is the latest, I'm wondering if there's a conflict with any elements in the page that might trigger this behavior.

Good job on this BTW !!!

Problems inside of a table?

Hi, thanks for the really nice plugin.
Seems inside of table it works not like expected.

In my test case the div.vsb-menu will displayed on top left corner of the browser.
In your demo page (i created a table around div#demo-single with dev-tools) your button doesn't react anymore.

Yes, i can try to work without tables. :-)

Slowdown of elements selection/unselection when large number of items

Hello,

I have a dropdown list of 3.372 elements.
Everything is working fine in v0.51 but when I decided to upgrade to the latest version (currently v0.57), I noted a slowdown of the script : When I check/uncheck elements, I have a mini freeze time, enough to be felt as a human user.
I will downgrade back to v0.51.

v0.51 :
https://user-images.githubusercontent.com/14607678/102622806-d2c90080-4141-11eb-9d42-966c3985ebe6.mov

v0.57 :
https://user-images.githubusercontent.com/14607678/102622815-d8264b00-4141-11eb-8694-5d888c412370.mov

this.root is nul

Hi, if i use the script global (in my case in the backend of a CMS) and i don't have a page with attribute "multiple", this JS error occours:
TypeError: this.root is null

It's not important, but can I avoid it?

"1 items" instead of "1 item"

Hello,

thank you for your project, it's very helpful for me.

I want to show only items count in the title zone, e.g. "1 item", "2 items" without actual values.

So if I use select like <select multiple="multiple" size="0"> I see "1 items" instead of "1 item".
2022-01-31_10-44

Do I need to use some option or it's just a bug?

Thank you.

How to use with require?

I am banging into an issue where the following:

const vanillaSelectBox = require('vanillaselectbox');

or

const vanillaSelectBox = require('vanillaselectbox/vanillaSelectBox');

both return empty objects.

I tried even just concatenating the file from node_modules into my main admin.js using webpack and get a similar issue.

Has anyone successfully used this in a more modern workflow that uses require and/or web pack?

InvalidCharacterError

If options have more as one class:
InvalidCharacterError: String contains an invalid character

In my case works not:
<option value="219" class="flag-padding flag-box"...
works:
<option value="219" class="flag-box"...

Options selected in SELECT tag appear in dropdown list without being initialized in VanillaSelectBox

I am using VanillaSelectBox in my project for its convenience and the controls offered, but I have a problem.

When I initialize a list with the SELECT tag with the options selected in base, they do appear in the VanillaSelectBox dropdown list after initialization, but are not saved like when I select manually. So, being limited to 3 choices, even if I have already made a selection, I can still choose 3 options instead of 2. I found a workaround to retrieve all selected values ​​from the SELECT tag and initialize with an array of values ​​that I pass to VanillaSelectBox via the setValues() method.

This is not very clean at the programming level, and requires additional work to compensate for the lack in VanillaSelectBox. It does half the job presenting the selections in the dropdown, I don't think it would be too complex to fix this feature, i hope.

Import as a module?

I'm trying to import this library as a module:

import "vanillaselectbox/vanillaSelectBox";

let mySel = new vanillaSelectBox("#my_id", {search: true});
mySel.enable();

but I get Uncaught ReferenceError: vanillaSelectBox is not defined error

How to force a fix width?

Hi guys... how to force a fix width in input type multiple?

I try using size atribut but the size of the field still moves

Autocomplete with limited size for huge data

Hello, thanks for this nice plugin!

Can I use this plugin for a search with huge data from server?
In this case I'd type in autocomplete input and content would be loaded on demand (showing max 10 items for example).

I checked the ajax demo example, but it gets all data. Trying to figure it out to redraw box with new content without create a new vanillaSelectBox() instance.

How to align the drop right

What is the best way to right align the drop, need this for a selectbox close to the rightside of the screen.

I tried it by replacing self.drop.style.left = self.left + "px"; by:
var caretright = document.getElementById("btn-group-" + self.domSelector).getElementsByClassName("caret")[0].getBoundingClientRect().right;
self.drop.style.float = "right";
self.drop.style.left = null;
self.drop.style.right = window.innerWidth - caretright - 10 + "px";

But maybe there is a better way.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.