npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

custom-select

v1.1.15

Published

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

Downloads

16,060

Readme

custom-select

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

Build Status

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="index.min.js" type="text/javascript"></script>

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