Pretty Select is a jQuery plugin to turn your old select boxes into pretty ones. With completely free hands on editing templates of select boxes and ability to load values dynamically, this plugin comes in handy for both beginners and skilled developers.

Simple select

Multiple select


Basic usage

Include js and css files

<head>
    <link rel="stylesheet" href="bootstrap.min.css">
    <link rel="stylesheet" href="prettySelect.css">
    <script src="jquery.min.js"></script>
    <script src="prettySelect.js"></script>
</head>

And call prettySelect() once the page is loaded.

$("select").prettySelect();

Default values

var settings = {
    action: "create",
    template: defaultTemplate,
    labelContent: labelContent,
    listItemContent: listItemContent,
    optionsHandler: null,
    listFilterHandler: filterList,
    customSearch: false,
    searchEnabled: true,
    searchDebounce: 150,
    allowDeselect: false,
    showAll: false,
    addButton: false,
    addButtonTemplate: "<div class='btn btn-default'>Add \"<b class='CONTENT'></b>\" option.</div>",
    addOptionForm: null,
    addOptionHandler: addNewOption
};

action ["create", "destroy", "options" or "value"]

create initiates prettySelect

destroy destroys prettySelect object and shows original select box

options returns list of all currently available options

value returns list of all selected values. (Most useful together with addButton)

template [string]

A main template putting everything together. [Example]

labelContent [function(content)]

Function returning content for label. content is content of label to render. (object or text depending on optionsHandler)

listItemContent [function(content)]

Function returning content for list item. content is content of list item to render. (object or text depending on optionsHandler)

searchEnabled [boolean]

If set to true, search bar is shown, else all available options are shown.

searchDebounce [integer]

It is highly recommended to set this above 0 if you load data through ajax.

customSearch [boolean]

If set to false (default), searchbar wrapper inherits style of label.

optionsHandler [function(searchText)]

searchText is searchbar content. This function should return array [object, object, ...] or json object {value:object}.

If array is returned, value is chosen by

  1. object.id
  2. object.value
  3. automatically from first available numeral value

It is possible to load options through AJAX.

listFilterHandler [function(searchText, value)]

First argument is content of searchbar, second argument is value of possible options. Value gets shown in option list if filter function returns true.

allowDeselect [boolean]

If set to true, it is possible to deselect values in simple select boxes. Does not affect multiple select

showAll [boolean]

If set to true, all options get shown, instead of just active ones.

addButton [boolean]

If set to true, it is possible to add new options. This is most useful for administration part of websites.

addButtonTemplate [html string]

This template is placed in the beginning of searchList

.CONTENT

Has class .selectAddButton. Text inside .CONTENT is synched with value of searchbar. If text is empty, this object also gets class .is-empty (doesn't affect default template)

addOptionForm [jQuery object or DOM element (<form>)]

If set to null, only value of searchbar is used to create new option.

If is set, values from selected form are used to add new option. This has to be used together with custom labelContent.

addOptionHandler [function(data, optionsData)]

data is value of submitted form (or value of searchbar, if form is not set).

optionsData are all the options currently available.

This function MUST return value for new option to be added, by default first non-taken numeral value is used. It is possible to fetch this value through AJAX.


Template explanation

All classes in uppercase are Pretty Select classes and are removed after template is rendered. This template as a whole is afterwards wrapped in <div class="prettySelect"></div> which is used for all control classes.
(.multiple or .simple depending on type of selectbox and .focused when Pretty Select is focused.)

var defaultTemplate = '<div class="WRAPPER form-control">\
    <div class="OPTIONS">\
        <div class="OPTGROUP">\
            <span class="LABEL label label-primary">\
                <span class="CONTENT"></span>\
                <span class="close REMOVE">&times;</span>\
            </span>\
        </div>\
    </div>\
    <div class="SEARCHLIST">\
        <div class="OPTGROUP">\
            <div class="CONTENT"></div>\
        </div>\
    </div>\
    <div class="SEARCHWRAP"><input class="SEARCH"><span class="glyphicon glyphicon-search"></span></div>\
</div>';

.WRAPPER gets class selectWrapper

Main wrapper used for default css, in previous versions was used to bind events, now is optional.

.OPTIONS gets class selectOptions

Options is a wrapper of all selected options (+ unselected if showAll:true).

.OPTGROUP gets class selectGroup

Is optional, if exists LABEL is considered template for label elements and also gets replaced by labels wrapper inside optgroup.

Label gets class selectLabel

.LABEL is template element for labels. If .OPTGROUP doesn't exist first element in .OPTIONS is considered label template.

.CONTENT is optional, it gets filled with items from labelContent, if it doesn't exist content gets prepended in the label.

.REMOVE is optional, gets appended by class selectRemove.

.SEARCHLIST gets class selectList

This is used as wrapper for search values. Not required if showAll:true.

.OPTGROUP gets class selectGroup

Is optional, if exists .CONTENT is replaced with options wrapper inside group. .CONTENT is still used as template for options.

.CONTENT gets class selectListItem

Gets filled with content from listItemContent.

.SEARCHWRAP gets class searchWrap

Searchwrap is optional. Use it, if you want your searchbar to inherit style of label.

.SEARCH gets class selectSearch

This class is only used to target for searchbar and to bind events.


With disabled options

$("select").prop("disabled",true);
$("option").prop("disabled",true);

(Disable reacts direcly to the state of parent selectbox.)

If you want to disable values passed in through optionsHandler, target option must contain disabled:true.


Optgroup support

<optgroup label="Parent" data-id="parent">
    ...
    options
    ...
</optgroup>

<optgroup label="Child" data-parent="parent">
    ...
    options
    ...
</optgroup>

data-id sets identifier of the rendered optgroup and data-parent targets to identifier of other optgroup. These are OPTIONAL and used for nesting only, it has no other use.

Simple select

Multiple select


Get options

if any of prettySelects exists
var options = $("select").prettySelect();
else

var options = $("select").prettySelect("options");

or

var options = $("select").prettySelect({
    action: "options"
});

Get values

$("select").on("change",function(){
    var value = $(this).val();
}); 

Simple select Current value:


                                

Multiple select Current value:


                                

Options of multiple selects


                        

Pretty Select with custom templates

var customTemplate = '\
<div class="WRAPPER customWrapper">\
    <h5>Custom template</h5>\
    <div class="OPTIONS">\
        <div class="customLabel">\
            <div class="REMOVE customRemove"><span class="glyphicon glyphicon-remove"></span></div>\
        </div>\
    </div>\
    <div class="SEARCHWRAP">\
        <div class="customSearchWrap">\
            <input class="SEARCH">\
            <div class="SEARCHLIST customList">\
                <div class="CONTENT customListItem"></div>\
            </div>\
        </div>\
    </div>\
</div>';
$("select").prettySelect({
    template: customTemplate,
    customSearch: true
});

Pretty Select without searchbar

$(".nosearch").prettySelect({
    searchEnabled: false
});

Simple select

Multiple select


Pretty Select with custom values
(extreme debounce time)

function customValues(wrapper, searchText) {
    return $.ajax(url);
};

$("select").prettySelect({
    optionsHandler: customValues,
    searchDebounce: 500
});

With search

Without search


Pretty Select with custom filter

function customFilter(searchText, value)
{
    if(value.indexOf(searchText) != -1)
    {
        return true;
    }
    return false;
}

$("select").prettySelect({
    listFilterHandler: customFilter,
    searchDebounce: 0
});

Custom case sensitive filter

Custom content usage
(This example is really stupid, but good for preview.)

function contentListItem(content) {
    return content.title;
}

function contentFilter(searchText, content) {
    content = content.title.toLowerCase();
    searchText = searchText.toLowerCase();
    if (content.indexOf(searchText) != -1)
    {
        return true;
    }
    return false;
}

var contentTemplate = '\
<div class="WRAPPER form-control">\
    <div class="OPTIONS">\
        <table class="table table-bordered">\
            <tr><td colspan="2"><span class="REMOVE close">&times;</span></td>\
            <tr><td>Color title</td><td>Inverse color preview</td></tr>\
            <tr class="CONTENT"></tr>\
        </table>\
    </div>\
    <div class="SEARCHLIST">\
        <div class="CONTENT"></div>\
    </div>\
    <div class="SEARCHWRAP"><input class="SEARCH"><span class="glyphicon glyphicon-search"></span></div>\
</div>';

$("select").prettySelect({
    optionsHandler: function () {
        return {
            "1": {"title": "Red", "hex": "00ffff"},
            "2": {"title": "Green", "hex": "ff00ff"},
            "3": {"title": "Blue", "hex": "ffff00"},
            "4": {"title": "Black", "hex": "ffffff"},
            "5": {"title": "White", "hex": "000000"}
        };
    },
    listFilterHandler: contentFilter,
    template: contentTemplate,
    labelContent: contentLabel,
    listItemContent: contentListItem,
    allowDeselect: true
});

Uses custom filter for content.title only.


Add button

$("select").prettySelect({
    addButton: true
});

Simple select

Multiple select

Advanced example

$("select").prettySelect({
    searchEnabled: false,
    showAll: true,
    addButton: true,
    addOptionForm: $("#form"),
    labelContent: personLabel
});

$("select").on("prettySelect.showForm", function (e, name) {
    $("#formName").val(name);
    $("#modal").modal('show');
});
$("select").on("prettySelect.hideForm", function () {
    $("#modal").modal('hide');
});

$("select").on("change", function () {
    console.log($(this).prettySelect("value"));
});

function personLabel(content) {
    var item = $("<span>");
    item.html(content.name + " is <b>" + content.age + "</b> years old");
    return item;
}                  

It is possible to press "enter" to add new option.

Selected values (If you want to send new data to server, this is the simples way.)


                                

To-Do list

  • High priority

    Optimisation

    I am not quite experienced with javascript, so there are possibly things that could be done better.

  • Order options function

    Possibility to order options by specific values. Work on this starts once I make sure, everything else is running nealy perfectly.

About

I am a 19 year old student from Czech Republic, who is trying to improve as much as possible. I am working on a personal project where I needed some way to load data through AJAX to selectbox but couldn't find anything online. Because of that I decided to create this and thought that other developers might find this useful too.

Also I would be most thankful for any help, response or ideas of how to improve this.


Developed by "Zane" Loučka