Giter Site home page Giter Site logo

mobius1 / selectr Goto Github PK

View Code? Open in Web Editor NEW
312.0 9.0 77.0 572 KB

A lightweight, vanilla javascript select box replacement. No dependencies.

License: MIT License

CSS 9.28% JavaScript 90.20% HTML 0.52%
vanilla-javascript vanilla-js vanilla-js-plugin select select-multiple selectbox tagging

selectr's Introduction

Selectr

npm npm version license Average time to resolve an issue Percentage of issues still open

NO LONGER UNDER ACTIVE DEVELOPMENT. If you would like to take over development please contact me and I'll transfer ownership.

A lightweight, dependency-free, mobile-friendly select box replacement written in vanilla javascript. Just 6.5KB minified and gzipped. Similar to Select2 and Chosen, but without the dependencies.

Supports most modern mobile and desktop browsers including IE9.

Don't forget to check the wiki out and view some demos.

Pull requests accepted!


Features:

  • Supports single and multiple select boxes
  • Supports optgroups
  • Custom datasets
  • Searchable options
  • Tagging support
  • Custom events
  • Custom styling
  • Native select UI for mobile devices
  • Dynamically add options
  • Much more...

Documentation | Demo


Install

bower

bower install mobius1-selectr --save

npm

npm install mobius1-selectr --save

Browser

Grab the files from one of the CDNs and include them in your page:

<link href="https://unpkg.com/mobius1-selectr@latest/dist/selectr.min.css" rel="stylesheet" type="text/css">
<script src="https://unpkg.com/mobius1-selectr@latest/dist/selectr.min.js" type="text/javascript"></script>

//or

<link href="https://cdn.jsdelivr.net/gh/mobius1/selectr@latest/dist/selectr.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.jsdelivr.net/gh/mobius1/selectr@latest/dist/selectr.min.js" type="text/javascript"></script>

You can replace latest with the required release number if needed.

CDNs courtesy of unpkg and jsDelivr


Initialisation

HTML

Start with a standard select box you want to convert:

<select id="mySelect">
	<option value="value-1">Value 1</option>
	<option value="value-2">Value 2</option>
	<option value="value-3">Value 3</option>
	...
</select>

Javascript

You can then instantiate Selectr by passing a reference to your select box as the first parameter as either a DOM node or a CSS3 selector string:

new Selectr(document.getElementById('mySelect'));

// or

new Selectr('#mySelect');

Selectr accepts the options object as a second parameter:

new Selectr('#mySelect', {
	searchable: false,
	width: 300
});

Contributors


If this project helps you then you can grab me a coffee or beer to say thanks.

paypal


License

Copyright 2016 Karl Saunders

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

selectr's People

Contributors

abduvakilov avatar adrian-enspired avatar aslafy-z avatar asppsa avatar ericboehs avatar istvanmakary avatar jmromeroes avatar jostermanatpew avatar maik-kluwe avatar mikeymckay avatar minajevs avatar mirkopulvirenti avatar mobius1 avatar pepe4 avatar reno1979 avatar rixafy avatar snrbrnjna avatar tchernyavskydaniil avatar xiapeixu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

selectr's Issues

Edge (+IE11) searchable option errors

Two things, both related to using the searchable option in Edge and IE11:

  1. The clear button is shown twice whilst the focus is with the input
  2. The 'no results' message is always shown once the second character is typed

_.input is not defined

I noticed that if I use the option {searchable:false}, it breaks the keyup event, since _.input is not defined.

on line 699, I encapsulate the rest of the keyup function within the if statement, so if e.target does in fact equal _.input, the rest of the code executes.

Enhancement: Add tabindex.

How can you build a select box replacement that doesn't even tab focus? This plugin needs a lot of work!

Trying to re-create select with ajax results.

Hi, I don know if I am writing the right code for do this.
I have 3 selects that needs to be filled by jquery based on a result from another select.
I am trying to use the new function with data, but the element don't reload new options content.

I have this element:

<select id="dimensions_ids" multiple class="form-control hidden-input" name="dimensions_ids[]" tabindex="-1" aria-hidden="true" disabled=""><option value="0"></option></select>

One option is needed because I can't create a selectr without nay option.

So, first I am initializing the element like this:

    let selectDimensionsIds = new Selectr('#dimensions_ids', {
        clearable: true
    });
    selectDimensionsIds.disable();

An I am trying to do this, but the options won refresh:

    function populateDimensions(areasId) {
        let values = {
            'areas': areasId
        };
        $.ajax({
            url: '/getdimensionsbyareas',
            type: 'GET',
            data: values,
            dataType: 'json',
            success: function(result) {
                let dimensions = JSON.stringify(result);
                selectDimensionsIds.destroy();
               selectDimensionsIds = new Selectr('#dimensions_ids', {
                    dimensions,
                    clearable: true,
                    multiple: true
                });
                selectDimensionsIds.enable();
            },
        });
    }

If someone could help me. I appreciate. Thanks

Search field should have autocomplete set to off

When typing into the searchable input field, Google Chrome sometimes thinks it's an address field and its hints overlay the actual list of results, annoyingly so.

Disabling autocomplete seems to help, so it would probably be best to add autocomplete: 'off' to the creation of the selectr-input.

Looking for Maintainer.

Due to me swapping to night shifts at my job I am no longer able to commit to maintaining this repo so instead of abondoning it I'd like to reach out to the community and see if any of you good people would like to get involved.

Let me know if you have the time and I'll add you as a collaborator.

Allow "x Selected" to keep the item single-line

Thank you very much for this great plugin.

Just a little enhancement idea: Could you add an option to keep the element single-line if more items than the width of the element are selected?
For example https://github.com/HemantNegi/jquery.sumoselect does that.
Or the selected items could end on "..." at the end of the line to indicate that there are more item selected.

There are several cases in layouts (compared to other native inputs (as filters e.g.)) where multiline is a problem.

Thank you very much again.

Safari first select value

Hi, with safari when submit form, all unselected field take first option. What I can check for fix?

Also in safari desktop option are not under correct select but more right.

i18n

Is there any way to include translations to the plugin?

Mobile non-native

I'm trying to disable the native version on mobile, is this possible or not ?
nativeDropdown defaults to true on mobile, but is there any way to counter that ?

Support for AJAX-loaded options?

I don't particularly want a full-blown lazy loading framework like select2 and friends (that would be unnecessary bloat IMO), but I'd still like some way of feeding async data into a selectr box.

My idea would be to add

  • removeOption / removeAllOptions methods to go alongside addOption
  • A search event triggered when anything is typed into the search box

Then I could have something along the lines of

var selectr = new Selectr("#my-lazy-select")

selectr.on("selectr.search", query => {
  if (query.length >= 3) {
    fetch("/results.json", { body: { query } }).then(results => {
      selectr.removeAllOptions()
      results.forEach(result => selectr.addOption(result))
    })
  }
})

... or something totally different (for example, with this approach having a loading spinner would be kinda annoying).

Let me know what you think :)

selectr.deselect & selectr.change event value

There is a bug when using a clearable select and listening to the selectr.change event. It appears that select.deselect fires before selectr.change and the selectr.change argument provides the previous value and not an empty value. This is a problem for my use case because I'm using selectr to control external actions.

Sample:

const selectr = new Selectr(selectNode, {
	clearable: true,
	defaultSelected: false,
	searchable: true,
});

selectr.on('selectr.deselect', (option) => {
	// do something with option value
});

selectr.on('selectr.change', (option) => {
	// when fired after a selectr.deselect event, option is the previous value and not an empty value
});

Option to disable hiding on scroll/resize

Selectr currently behaves much like a browser-default select box in that the dropdown hides on scroll and resize.

However, this isn't always ideal. It would be great to have an option, i.e. preventClosing that can be activated in order to stop the dropdown from closing whenever you scroll.

A lot of people constantly have their finger on the scrolling wheel and it can get frustrating whenever the dropdown closes seemingly for no reason, just because you wanted to adjust the screen position.

Cannot Create Selectr From Empty <select>

Passing an empty <select> (no child <option>s) triggers an error:

Error: You don't have any options in your select!

Is this really a problem? Why can Selectr not simply build an empty select list?

thanks for your time!

how to not overlaping other divs

i have a dinamic div build on excution time on clien side , and also a select with your' implementation..

both inputs are the my firts, and then below the select with selectr implementation..

when i try to display the firts input , the div are redndered, but the "search" input of the selectr overlaping the others, see the picture, the firts input display a list, the second its the select with selectr implementation and overlaing the rendering of the firts:

selectr-overlaping

lack of good documentation, usage are not good

i try u'r good library, but the lack of CLEAR documentation make many users lack of usage it!

when i try the pickathing flavor for the select with search combobox i got a easy to implement javascript select input box, that works at firts try..

with u'r documentation (that not explain where to put or how the js code) i need to try many times until got with some good results

  1. not clear about how:
... and include the JS file near the bottom of your document's body
<script type="text/javascript" src="/path/to/selectr.min.js"></script>

what exaclty means "near", its vage and ambigous, and hard to do if it use a frameworks (that many put many code at the "near" of the end body tag)

  1. complety miscunderstand about initialization:
var mySelect = document.querySelector('select');
var mySelectr = new Selectr(mySelect);

the piece of code generates two errors (depending):
2.1 * selectr.min.js:107 Uncaught TypeError: this.elem.getBoundingClientRect is not a function
this is at Plugin (selectr.min.js:107)
2.2 * seletr need and element id to work
this is when using exactly the documentation suggested, due the right way its document.getelementById in novice cases, althrought i dont nkow if its the right way

i posted and iisue about the last

i can help with good documentation but i need more eplaint and comments in the code, due in'm not expert

add option not working

var selector2 = new Selectr("#someID");

    selector2.addOption({
value: "some-value",
text: "Some Text"

});

error: selectr need and element id to work

2.2 * seletr need and element id to work
this is when using exactly the documentation suggested, due the right way its document.getelementById in novice cases, althrought i dont nkow if its the right way

documentation said that i need to do:

var mySelect = document.querySelector('select');
var mySelectr = new Selectr(mySelect);

but the document.querySelector('select') returns the firts input selector and this confuses novice users when try to use in and multi html where the id and name input select are same, and are multiple selects inputs

so documentation must be more clear, or are incorrect

defaultSelected not working

Thank you for your very useful library.

When I have:

<select name="label[px_per_mm]" id="label_px_per_mm">
  <option value="8">Low Def</option>
  <option value="12">High Def</option>
</select>

And run this:

new Selectr('#label_px_per_mm', {defaultSelected: true})

The first option (8/Low Def) is not selected as I would expect (and as per the standard select behaviour).

Double Selections

When creating a multi-select, build calls getSelectedProperties() to set this.selectedValues and this.selectedIndexes. The former works fine; but the latter gets an empty array (because idx has not yet been set on any of the options).

Later, this causes selected values to be added to this.selectedValues again, since select() uses this.selectedIndexes (which, as noted above, is empty at this point) to detect duplicates.


I wasn't sure what the best solution would be for this. My first thought would be to always set selectedValues by looking up options in selectedIndexes, instead of maintaining the two lists separately, but I'm not sure if this would have a negative impact on anything else, so I'm looking for feedback. If this is a practical solution, I can implement and PR.

Couple of issues and suggestions

We had some several issues with this select.

  1. Empty select throws error - I saw that there will be fix in next release

  2. Selectr prevents select to set its default value - By default select sets its default value from first option child, therefore select has some valid value. But Selectr prevents this and instead of "some value" select has value of NULL which is a big problem in our occasion because our validation service doesnt allow NULL as valid value. So we added an option with value of "" ............ troubles continues in next point......

  3. Empty option breaks script - If you add option with no value, Selectr throws error. See code below.

<select id="test"> <option value=""></option> <option value="yolo">John Doe</option> </select>

  • I have fixed this by modifying line: 461 -> changed (option.nodeName !== "OPTION" || !option.value) to (option.nodeName !== "OPTION" && !option.value)
  1. Selectr doesn't emit "onchange" event for select - It would be nice if Selectr could provide this by default. In case that somebody will need this, see code below
    element.on('selectr.select', function(option) { let sel = option.parentNode; if ("createEvent" in document) { let evt = document.createEvent("HTMLEvents"); evt.initEvent("change", true, true); sel.dispatchEvent(evt); } else { sel.fireEvent("onchange"); } });

  2. Enter new tag input placeholder - It would be nice if we could change "Enter a tag..." placeholder for this input directly in Selectr options. If there is such option in Selectr already, then sorry, I didn't saw that :)

Those first 3 points made us suffer so badly, it took us 1 and a half day to figure everything out :D
But no hate sir! I think this library is great!
Thank you for your effort, time and MIT license :)

Mobile style

Hi, there's an option for show mobile select as a list how normal select? Thanks!

Fallback to native interface on mobile devices

It would be awesome if on mobile devices when interacting with the select it could use the native interface provided by the OS. Perhaps as an option so that if some people wanted to keep the search functionality etc around, they could.

Thanks for the great lib!

Highlight the top result when searching

Hi,

I just noticed from playing around in the demo that you can't type to search and then press Enter to select the top search result (instead it selects whatever you'd hovered before you started searching). To me it would make sense to highlight the top search result when you enter text in the search box, unless your currently highlighted item is still in the list of search results - does that make sense?

Cheers! (and thanks for making this, I'm super impressed by how featureful and lightweight it is)

form.reset() doesn't clear Selectr elements

When you use the form.reset() method on a form element, it resets all inputs, and other form elements contained in the form to their default values. Any selectr-ised select boxes do not reset. You have to use the selectr.reset() method for each of them individually.

For reference: MDN: HTMLFormElement.reset()

Otherwise, Selectr.js works exactly how I expect. Thanks for making it!

Dropdown doesn't calculate height of search field

The open function seems to be based on the height of the selectr-options list and doesn't take the height of the search field into consideration:

var doInvert = _.elRect.top + _.elRect.height + _.optsRect.height > wh;

This results in a partially hidden dropdown box if it's close enough to the bottom of the window.

Additionally, because scrolling the page causes the dropdown to toggle, this makes it practically impossible to view the cut-off part of the dropdown.

It would be preferable to instead use the height of the selectr-options-container in the inversion calculation.

Plugin started while including (with missing DOM arg), before call

Reproducing Steps:

  1. npm install mobius1-selectr --save
  2. require("mobius1-selectr")

(!) Here I got next one:

selectr.js:922 Uncaught Error: You must supply either a HTMLSelectElement or a CSS3 selector string.
at Object.m (selectr.js:922)
at s.defaultSelected (selectr.js:11)
at Object. (selectr.js:15)
at t (bootstrap aaae86e04d25fb32a59e:19)
at Object. (_components.js:27)
at t (bootstrap aaae86e04d25fb32a59e:19)
at Object. (index.js:5)
at t (bootstrap aaae86e04d25fb32a59e:19)
at bootstrap aaae86e04d25fb32a59e:62
at bootstrap aaae86e04d25fb32a59e:62

  1. new Selectr(document.getElementById('taggable'));

If I understood right - plugin run on step#2 (require ...), not step#3 (new Selectr...), but why?
Explain or Fix, please.. thx.

Webpack issue

I was trying to get it to work with webpack for hours with no luck.
What is weird, its self invoking immediately, without being instanciated.
It throws error: this.el is undefined. Pointing to line 1596 where is condition if (this.el.nodeName.toLowerCase() !== "select") {
This is what Im getting after compilation in anonymous function defined at the top of your script:
if (true) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory(plugin)), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object") { module.exports = factory(plugin); } else { root[plugin] = factory(plugin); } })(undefined, function (plugin) { "use strict";

Multiple instances can be open at the same time

I noticed that when I have multiple instances of selectr on my page, I can have all of them open at the same time.
From what I gather this - imho unintended - behaviour is caused by these lines of code:

		// Non-native dropdown
		this.selected.addEventListener("click", function(e) {

			if (!that.disabled) {
				that.toggle();
			}

			e.stopPropagation();
			e.preventDefault();
		});

The call to e.stopPropagation() prevents other instances (or in fact any other element on the page) from reacting to the click event.
As far as I could see there is not really a reason for the stopPropagation, at least removing it did not lead to any strange behaviour in my app.

setValue

I have a issue whit a function setValue my bowser send e error ReferenceError: _forEach is not defined

`

<title>TEST</title> <script type="text/javascript" src="Selectr/selectr.min.js"></script> Aucune categorie Français Biologie Mathematique Physique Histoire Géographie Autre Informatique
	<button id="myButtonMulti" class="btn btn-primary">Set Values</button>

	<script type="text/javascript">
		var mySelectr = new Selectr(document.getElementById('category'), {
		searchable: true,
		width: 300
		});

		mySelectr.setValue(['1', '2', '3']);
		
	</script>
</body>
`

AJAX & Adding options on iPad/ios [bug]

Hey,

I've noticed that there is a slight issue when dynamically changing options (.removeAll then .add multiple times) on IOS/my ipad more specifically. Can be reproduced in Chrome by selecting iPad in dev tools.

The drop-down will work on Desktop devices, but not my iPad - I took a look it was fixed by adding a this.el.appendChild(option); to .add, however, i imagine this isn't the ideal solution and I didn't have too much time to look into it, so couldn't seen if that was a correct way to fix it!

I understand you fall back to the native dropdowns - which is great, however, the issue is that no options are added at all when using .add :(

Thanks
Kieran

selecting selected option breaks the select box

If I click on the option that is already selected, the select box height shrinks because there is no padding above or below the text, and the selected option is now "choose..." This is definitely not the correct behavior for a modern select box.

I went to line 495 and commented out the following lines

//if (util.hasClass(opt, "selected")) {
//    deselect.call(_, index);
//} else {
   select.call(_, index);
//}

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.