mousemke / flounder

Style-able dropdown replacement for native dropdowns
MIT License
9 stars 10 forks source link

Flounder.js 1.3.13

Flounder build status

(for modern browsers and ie10+)

Flounder is a styled select box replacement aimed at being easily configurable while conforming to native functionality and accessibility standards.

// npm
require('flounder');

// es6
import Flounder from 'flounder';

Usage

Flounder can be used in vanilla js, requirejs, jquery, and microbe.

Flounder can also be used in react, however there is a seperate repo for that

// vanilla
new Flounder( target, configOptions );

// requirejs
requirejs( [ 'flounder' ], function( Flounder )
{
    new Flounder( target, configOptions );
} );

// jQuery plugin
$( '.example--class' ).flounder( configOptions );

// microbe plugin
µ( '.example--class' ).flounder( configOptions )

Flounder also adds a reference of itself to its target element. So if you lose the reference, you can just grab it from the element again

document.querySelector( '#vanilla--select' ).flounder.destroy()

Target options

Flounder's target is quite flexible, however it will only build on the first element it finds.

you can give it an element:

new Flounder( document.getElementsByTagName( 'input--el' )[0], configOptions );

an HTML collection:

new Flounder( document.getElementsByTagName( 'input' ), configOptions );

a jQuery object:

new Flounder( $( 'input' ), configOptions );

a microbe:

new Flounder( µ( 'input' ), configOptions );

or, just a selector string:

new Flounder( 'input', configOptions );

If flounder is fed an element that already has a flounder, it will destroy it and re initialize it with the new config options.

Available config options

{
    allowHTML               : false,
    classes                 : {
        ARROW                 : `class-for-arrow-wrapper`,
        ARROW_INNER           : `class-for-arrow-inner`,
        DESCRIPTION           : `class-for-option-description`,
        DISABLED              : `class-for-disabled`,
        HEADER                : `class-for-header`,
        HIDDEN                : `class-for-hidden`,
        HIDDEN_IOS            : `class-for-hidden-ios`,
        HOVER                 : `class-for-hover`,
        LIST                  : `class-for-list`,
        LOADING               : `class-for-loading`,
        LOADING_FAILED        : `class-for-loading-failed`,
        MAIN                  : `class-for-flounder`,
        MAIN_WRAPPER          : `class-for-wrapper`,
        MULTIPLE_TAG_FLOUNDER : `class-for-multiple`,
        MULTI_TAG_LIST        : `class-for-multi-tag-list`,
        MULTIPLE_SELECT_TAG   : `class-for-multiple-select-tag`,
        MULTIPLE_TAG_CLOSE    : `class-for-multiple-tag-close`,
        NO_RESULTS            : `class-for-no-results`,
        OPEN                  : `class-for-open`,
        OPTION                : `class-for-option`,
        OPTION_TAG            : `class-for-option-tag`,
        OPTIONS_WRAPPER       : `class-for-list-wrapper`,
        PLACEHOLDER           : `class-for-placeholder`,
        PLUG                  : `class-for-ios-plug`,
        SECTION               : `class-for-section`,
        SELECTED              : `class-for-option-selected`,
        SELECTED_HIDDEN       : `class-for-option-selected-hidden`,
        SELECTED_DISPLAYED    : `class-for-option-selected-displayed`,
        SEARCH                : `class-for-input-search`,
        SEARCH_HIDDEN         : `class-for-search-hidden`,
        SELECT_TAG            : `class-for-select-tag`
    },
    data                    : dataObject,
    defaultEmpty            : true,
    defaultValue            : defaultValue,
    defaultIndex            : defaultIndex,
    disableArrow            : false,
    keepChangesOnDestroy    : false,
    multiple                : false,
    multipleTags            : false,
    multipleMessage         : '(Multiple Items Selected)',
    noMoreOptionsMessage    : 'No more options to add',
    noMoreResultsMessage    : 'No matches found',
    onChange                : function( e, valueArray ){},
    onClose                 : function( e, valueArray ){},
    onComponentDidMount     : function(){},
    onComponentWillUnmount  : function(){},
    onFirstTouch            : function( e ){},
    onInit                  : function(){},
    onInputChange           : function( e ){},
    onOpen                  : function( e, valueArray ){},
    openOnHover             : false,
    placeholder             : 'Please choose an option',
    search                  : false,
    selectDataOverride      : false
}

IMPORTANT DEFAULT PRIORITY

1 ) placeholder
2 ) defaultIndex
3 ) defaultValue
4 ) whatever is at index 0

Building the select box

selectbox data must be passed as an array of objects

[
    {
        text        : 'probably the string you want to see',
        value       : 'return value',
        description : 'a longer description of this element', // optional, string
        extraClass  : 'extra--classname',                   // optional, string
        disabled    : false                                 // optional, boolean
    },
    ...
]

or a simple array of strings. The passed text will be both the text and the value. There would be no description in this case

[
    'value 1',
    'value 2',
    'value 3',
    ...
]

or, if you want section headers. You can even add uncatagorized things intermingled

[
    {
        header : header1,
        data : [ option1, option2, ... ]
    },
    {
        text        : 'probably the string you want to see',
        value       : 'return value',
        description : 'a longer description of this element'
    },
    {
        header : header2,
        data : [ option1, option2, ... ]
    },
    ...
]

all extra properties passed in an option that are not shown here will be added as data attributes for the sake of reference later. The data can be accessed in the init (before building) as this.data if they need reformatting or filtering.

API

These functions are intended for use in the user provided event callbacks

this.buildFromUrl( url, callback )
this.clickByIndex( index, multiple* )
this.clickByText( text, multiple* )
this.clickByValue( value, multiple* )
this.deselectAll( silent )
this.destroy()
this.disable( bool* )
this.disableByIndex( index )
this.disableByText( text )
this.disableByValue( value )
this.enableByIndex( index )
this.enableByText( text )
this.enableByValue( value )
this.getData( num* )
this.getSelected()
this.getSelectedValues()
this.loadDataFromUrl( url, callback )
this.props
this.rebuild( data*, props*  )
this.refs
this.setByIndex( index, multiple* )
this.setByText( text, multiple* )
this.setByValue( value, multiple* )

*optional

npm scripts

Contributing

Development of Flounder requires node '7.0.0' or higher.

Flounder's branch structure goes as follows:

Releasing

When you release a new verion, commit it to master, then commit it to release. It must be released from the release branch. It is the only branch that commits the dist files

We gladly accept and review any pull-requests into the current dev branch. Feel free! :heart:

Otherwise, if you just want to talk, we are very easy to get a hold of!

This project adheres to the Contributor Covenant. By participating, you are expected to honor this code.

Flounder - Code of Conduct

Need to report something? flounder@knoblau.ch

Example

Given the example data:


    var data = [
        {
            cssClass    : 'select-filters',
            id          : 'All',
            isTaxonomy  : true,
            text        : 'All'
        },
        {
            cssClass    : 'category',
            id          : 'category',
            isTaxonomy  : true,
            text        : 'Categories'
        },
        {
            cssClass    : 'tag',
            id          : 'tag',
            isTaxonomy  : true,
            text        : 'Tags'
        }
    ];

a vanilla flounder

flounder can be attached to basically anything


    new flounder( document.getElementById( 'example' ), {
        placeholder         : 'placeholders!',

        onInit              : function()
        {
            var res = [];
            data.forEach( function( dataObj )
            {
                res.push( {
                    text        : dataObj.text,
                    value       : dataObj.id
                } );
            } );

            this.data = res;
        }
    } );

The result of these is shown here (only styled with the structural css)

closed

closed

open menu

open menu

1 selected

1 selected

See more examples on the demo page

Change Log

1.3.0

1.2.1

1.2.0

1.1.1

1.1.0

1.0.1

1.0.0

Older Changes

To keep the length of this file down, older changes are here