Giter VIP home page Giter VIP logo

custom-select's Introduction

custom-select

A lightweight JavaScript library for custom HTML <select> creation and managing. No dependencies needed.

Build Status npm npm

Demos

Base
Bootstrap
Control buttons
GSAP
jQuery
Mobile Touch Devices

Install

Install with npm (recommended)

$ npm install --save custom-select

Or download the minified build file here. (jquery version is alternative, not needed!)

Use

With ES6 modules via the import statement:

import customSelect from 'custom-select';

In CommonJs environments with the require function:

var customSelect = require("custom-select").default;

Note: the require().default is necessary due to the babelify export system.

In HTML with the script tag:

<script src="custom-select.min.js" type="text/javascript"></script>

and optionally:

<link rel="stylesheet" href="custom-select.css">

How it works

Start with a simple HTML <select>:

<select id="mySelect">
  <option value>Select...</option>
  <option value="foo">Foo</option>
  <option value="buz">Buz</option>
</select>
customSelect('select');

You can nest the select in their label or you can use the for attribute on the label. Nested will work fine but it's formally wrong due to label element specification: only a select element can be nested in a label tag.

Here's the HTML result:

<div class="custom-select-container customSelect">
  <span class="custom-select-opener" tabindex="0">
    <span>Select...</span>
  </span>
  <select id="mySelect1">
    <option value>Select...</option>
    <option value="foo">Foo</option>
    <option value="buz">Buz</option>
  </select>
  <div class="custom-select-panel">
    <div class="custom-select-option is-selected has-focus" data-value="">Select...</div>
    <div class="custom-select-option" data-value="foo">Foo</div>
    <div class="custom-select-option" data-value="buz">Buz</div>
  </div>
</div>

Also state classes will be added and removed while plugin working.

You can use default css included in plugin release or style it by yourself. You can also use advanced techniques for using native select on Mobile/touch devices. Check the examples for inspirations.

Plugin init

Array customSelect(elements[, pluginOptions]);

The elements parameter could be:

A DOMString selectors:

customSelect('.myForm .mySelect');

A instance of HTMLElement, tag SELECT:

customSelect(document.getElementById('mySelect'));

A list (NodeList, HTMLCollection, Array, etc) of instances of HTMLElement, tag SELECT:

customSelect(document.querySelector('.mySelect'));
//or
customSelect(document.getElementsByClassName('mySelect'));

The pluginOptions parameter is an object that overwrites some default plugin configurations.

The default config is:

{
  containerClass: 'custom-select-container',
  openerClass: 'custom-select-opener',
  panelClass: 'custom-select-panel',
  optionClass: 'custom-select-option',
  optgroupClass: 'custom-select-optgroup',
  isSelectedClass: 'is-selected',
  hasFocusClass: 'has-focus',
  isDisabledClass: 'is-disabled',
  isOpenClass: 'is-open'
}

The return is an Array of customSelect instances, that contains all the public exposed methods and properties.

Style Classes

All css classes can be configured using pluginOptions, except container secondary class customSelect which is only for internal use and should not be removed or used for styling purpose.

Structure Classes

Self explained structure classes, and relative may-have status classes:

containerClass: 'custom-select-container' may have isDisabledClass, isOpenClass

openerClass: 'custom-select-opener'

panelClass: 'custom-select-panel'

optionClass: 'custom-select-option' may have isSelectedClass, hasFocusClass

optgroupClass: 'custom-select-optgroup'

State Classes

isSelectedClass: 'is-selected' - when the custom option is selected (as native selected attribute).

hasFocusClass: 'has-focus' - when the custom option has current focus (mouseover, arrow navigation and keyboard autocomplete changes the focus).

isDisabledClass: 'is-disabled' - when the select is disabled.

isOpenClass: 'is-open' - when the panel is open.

How to get Plugin instance

Init return

const cstSel = customSelect('select')[0]; // return is an array of instances!
console.log(cstSel.open); // true|false

The DOM select

customSelect('select');
const cstSel =  document.querySelector('select').customSelect
console.log(cstSel.open); // true|false

The DOM select container

customSelect('select');
const cstSel =  document.querySelector('.customSelect').customSelect
console.log(cstSel.open); // true|false

Methods & Properties

pluginOptions property [readonly]

Get the plugin options.

cstSel.pluginOptions;

open property

Get/set property.

cstSel.open = true; // open the custom select
console.log(cstSel.open); // true
cstSel.open = false; // close the custom select
console.log(cstSel.open); // false

disabled property

Get/set property.

cstSel.disabled = true; // disable the custom select
console.log(cstSel.disabled); // true
cstSel.disabled = false; // enable the custom select
console.log(cstSel.disabled); // false

value property

Get/set property.
Change both the native select and the custom select. Use it just like nativeSelect.value

cstSel.value = 'foo'; // the first option with that value will be selected. If there is no option with that value the first one'll be selected.
console.log(cstSel.value); // return foo if there was an option with 'foo' value

append(elements[, target]) method

Append an option or an optgroup to the select.

const option = document.createElement('option');
option.text = 'Foo';
option.value = 'bar';
cstSel.append(option);

The elements parameter could be:

An instance of HTMLElement, tag OPTION:

const toBeAppend = document.createElement('option');

An instance of HTMLElement, tag OPTGROUP:

const toBeAppend = document.createElement('optgroup');

A list (NodeList, HTMLCollection, Array, etc) of instance of HTMLElement, tag OPTION/OPTGROUP:

const toBeAppend = cstSel.empty();

The target parameter must be the select (default) or an optgroup that is already inside the select.

insertBefore(elements, target) method

insert an option or an optgroup before the specified target.

const option = document.createElement('option');
option.text = 'Foo';
option.value = 'foo';
const target = cstSel.select.options[2];
cstSel.insertBefore(option, target);

The elements parameter could be:

An instance of HTMLElement, tag OPTION:

const toBeAppend = document.createElement('option');

An instance of HTMLElement, tag OPTGROUP:

const toBeAppend = document.createElement('optgroup');

A list (NodeList, HTMLCollection, Array, etc) of instance of HTMLElement, tag OPTION/OPTGROUP:

const toBeAppend = cstSel.empty();

The target parameter must be an option or an optgroup that is already inside the select.

remove(node) method

remove an option or an optgroup

cstSel.remove(cstSel.select.options[1]);

empty() method

empty the select

cstSel.empty();

destroy() method

destroy the plugin, removing custom markup, classes, and listeners.

cstSel.destroy();

opener property [readonly]

DOM Element

select property [readonly]

DOM Element

panel property [readonly]

DOM Element

container property [readonly]

DOM Element

Events

custom-select:open

Only on container.

cstSel.container.addEventListener('custom-select:open',
  (e) => { console.log(`${e.target} is open ๐Ÿ˜Š`)});

custom-select:close

Only on container.

cstSel.container.addEventListener('custom-select:close',
  (e) => { console.log(`${e.target} is closed ๐Ÿ˜”`)});

custom-select:disabled

Only on container.

cstSel.container.addEventListener('custom-select:disabled',
  (e) => { console.log(`${e.target} is disabled ๐Ÿ‘‹`)});

custom-select:enabled

Only on container.

cstSel.container.addEventListener('custom-select:enabled',
  (e) => { console.log(`${e.target} is enabled ๐Ÿ‘`)});

custom-select:focus-outside-panel

Fired on custom option, recommended listener on panel.

This CustomEvent fires when the focused option moves outside the visible part of the panel.
It bubbles, so the listener can be placed on every ancestor of the custom options.
This event is useful for custom animations on select's autocomplete-search, when the focus moves to the found option. By default there's no animation but a simply scrollTop change of the panel.
You can overwrite this behaviour by simply adding an EventListener, with useCapture argument set to true and an e.stopPropagation() statement inside you listener's callback-function.

// Example with jQuery animate
cstSel.panel.addEventListener('custom-select:focus-outside-panel',
  (e) => {
    e.stopPropagation();
    $(cstSel.panel).animate({
      scrollTop: e.target.offsetTop,
    }, 300)
  }, true);

change

Only on select.

cstSel.select.addEventListener('change',
  (e) => { console.log(`${e.target} has changed it's value ๐Ÿ‘Œ`)});

jQuery adaptor

If you really can't live without jQuery, an adaptor was made for you ๐Ÿ˜ฉ: download jQuery version here.

jQuery init

$('#mySelect').customSelect();

jQuery property set

$('#mySelect').customSelect('open', true);

jQuery property get

$('#mySelect').customSelect('open');

jQuery methods

$('#mySelect').customSelect('remove', $('#mySelect')[0].options[1]);

That's all folks!

And now have fun โœŒ

Browser support

Oh wait, I was almost forgetting:

  • Chrome
  • Safari 7.0
  • Firefox 10 (maybe also older, but come on...)
  • Android 4.0
  • Mobile Safari 6.0
  • Internet Explorer 10

custom-select's People

Contributors

ge1i0n avatar gionatan-lombardi avatar marconucara 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

Watchers

 avatar  avatar  avatar  avatar

custom-select's Issues

IE11 have two problem

  1. "TypeError: Unable to get property 'customSelect' of undefined or null reference
  2. select.addEventListener('change', function(e) { console.log(e) });

This code don't work. And event does not come.

Native mobile example not working on codesandbox

Hi!
Your package works perfect. Easy to setup and I was busy in no time.

I tried to follow the example for the native select on mobile (so you get the OS select instead of the custom-select one). This isn't working on iOS somehow. Any idea how to fix this? or am I missing something?
Thanks!

JQuery adaptor

From @nuky89 on September 1, 2016 15:36

Would be nice to have a jquery adapter. Behavior TBD.

Copied from original issue: gionatan-lombardi/custom-select#8

Custom select doesn't support multiple version

Improvement on the plugin :
A select with multiple attributes is not processed correctly.

<select id="mySelect" multiple>
      <option value>Select...</option>
      <option value="foo">Foo</option>
      <option value="buz">Buz</option>
</select>

Should allow the user to select multiple options, this feature doesn't seem integrated at all but is somewhat important in some cases.

Options disabled attribute

Options could have disabled attribute.

What is involved:

  • disabled options can not be clicked
  • disabled options can not be selected programmatically (TODO: check native bheavior)
  • keyboard navigation have to skip disabled options
  • disabled custom select options need a class for disabled style
  • we should offers a method for enable/disable options
  • others?

Re-render panel with current <select> state

Hi, I'm trying to make a custom dropdown in Angular, and I'm running in the problem with syncing the native select with the custom panel. The Angular template engine creates/updates the select and option, but then I run in to the trouble in updating the custom panel.

I tried several things

  • If I only run customSelect once, I get an empty dropdown because of order of execution and option not being added yet.
  • if I run customSelect on every template update, the select keeps being decorated with the custom dropdown until my browser crashes...
  • If I try to empty and rebuild it, I end up with no option selected or the error parentNode not found. I also have trouble updating the select when the select is open.
  • If I try to only add options if they have no property customSelectCstOption I do add new options if they are added, but it's a hack and the order is incorrect.

So what is the correct solution to update the custom selection if the native select is being updated outside this library?

Include build directory in repo.

Great plugin - however, we're handcuffed a bit due to our setup which prevents us from running npm run build on our deployments to create the /build directory. Please include the /build directory in the repo codebase by default.

Scroll propagation

When you scroll on the custom select panel the scroll shouldn't be propagated at parent elements.

A stopPropagation() call may be enough?

Is this project active?

Hi all.

I want to help, but I want to know if this project is active. Is this project active?

Refresh custom select

Hello,
Is there a method or a simple way to refresh the custom select, after updating the select ?

Thanks

No working With Bootstrap 4 beta 2 css

Only work with bootstrap 4 alpha example

`

<title>Document</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" integrity="sha384-2hfp1SzUoho7/TsGGGDaFdsuuDL0LX2hnUp6VkX3CUQ2K4K+xjboZdsXyp4oUHZj" crossorigin="anonymous">

<link rel="stylesheet" href="css/custom-select.css">

<style type="text/css">
	.dropdown-optgroup {
		border-top: 1px solid #e5e5e5;
		margin-top: 6px;
		padding-top: 6px;
		padding-bottom: 6px;
	}
	.dropdown-optgroup::before {
		content: attr(data-label);
		display: block;
		padding: 3px 20px;
		font-weight: bold;
	}
	.dropdown-item {
		cursor: pointer;
	}
</style>
<label for="mySelect2">Select with optgroup</label>
<select id="mySelect2">
	<option value>Select...</option>
	<optgroup label="Cips">
		<option value="zizz">Zizz</option>
	</optgroup>
	<optgroup label="Lips">
		<option value="fruit">mango</option>
		<option value="flower">rose</option>
		<option value="fruit">pineapple</option>
		<option value="flower">lotus</option>
		<option value="flower">lily</option>
		<option value="lorem">Lorem ipsum dolor</option>
	</optgroup>
</select>


<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>


<script src="js/custom-select.min.js"></script>


<script>
	if (typeof require !== 'undefined') {
	  var customSelect = require("custom-select").default;
	  require("css/custom-select.css");
	}
	customSelect('#mySelect2', {
	  openerClass: 'btn btn-info btn-block dropdown-toggle',
	  panelClass: 'dropdown-menu bg_dark w-100',
	  optionClass: 'dropdown-item',
	  optgroupClass: 'dropdown-optgroup',
	  isOpenClass: 'open',
	});
</script>
`

if add the https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css fails

Webcomponent wrapper

From @nuky89 on September 6, 2016 15:17

Create a Webcomponent wrapper.

Copied from original issue: gionatan-lombardi/custom-select#15

Add base css

From @gionatan-lombardi on September 6, 2016 15:13

It will be used in the examples and for plugin instant use.

Copied from original issue: gionatan-lombardi/custom-select#13

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.