Skip to content

damian-rodriguez-sociomantic/flounder

 
 

Repository files navigation

Flounder.js 0.8.5

*** Flounder 1.0.0 is being built right now, so there is a feature freeze on earlier versions, but feel free to open issues for 0.X.X and feature issues for 1.0.0 should anything come up ***

Flounder build status

(for modern browsers and ie9+)

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.

// 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.

you can give it an element:

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

an array:

new Flounder( [ el1, el2, el3 ], options );

an HTML collection:

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

a jQuery object:

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

a microbe:

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

or, just a selector string:

new Flounder( 'input', options );

If flounder is fed an element that already has a flounder, it will destroy it and re initialize it with the new 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`,
        DISABLED_OPTION       : `class-for-disabled-option`,
        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_SELECTED     : `class-for-multiple-selected`,
        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)',
    noMoreOptionsText       : 'No more recipients to add.',
    noResultsText           : 'No matches found.',
    onClose                 : function( e, valueArray ){},
    onComponentDidMount     : function(){},
    onComponentWillUnmount  : function(){},
    onFirstTouch            : function( e ){},
    onInit                  : function(){},
    onInputChange           : function( e ){},
    onOpen                  : function( e, valueArray ){},
    onSelect                : function( e, valueArray ){}
    openOnHover             : false,
    placeholder             : 'Please choose an option',
    search                  : false,
    selectDataOverride      : false
}
  • allowHTML- (boolean) Renders the data text as HTML. With this option enabled, any api call that must compare text will need the exact html in order to be a match

  • classes- (object) Custom CSS classes for Flounder DOM elements (overrides defaults; only the classes specified will be overridden).

  • data - (array) select box options to build in the select box. Can be organized various ways

  • defaultEmpty- (boolean) first in priority, this makes the flounder start with a blank valueless option

  • defaultValue - (string) Sets the default value to the passed value but only if it matches one of the select box options. Multi-tag select boxes only support placeholders

  • defaultIndex - (number) Sets the default option to the passed index but only if it exists. This overrides defaultValue. Multi-tag select boxes only support placeholders.

  • disableArrow - (boolean) does not add the dropdown arrow element

  • keepChangesOnDestroy - (boolean) Determines whether on destroy the old element is restored, or the flounder changes to the select box are kept. This only applies when the initial element for flounder is a select box

  • multiple - (boolean) Determines whether it is a multi-select box or single

  • multipleTags - (boolean) Determines how a multi-select box is displayed

  • multipleMessage - (string) If there are no tags, this is the message that will be displayed in the selected area when there are multiple options selected

  • noMoreOptionsText - (string) text displayed when multipleTags is true and there aren't more options to select,

  • noResultsText - (string) text displayed when the search is true and its value doesn't match any option

  • onClose - (function) Triggered when the selectbox is closed

  • onComponentDidMount - (function) Triggered when the selectbox is finished building

  • onComponentWillUnmount - (function) Triggered right before flounder is removed from the dom

  • onFirstTouch - (function) Triggered the first time flounder is interacted with. An example usage would be calling an api for a list of data to populate a drop down, but waiting to see if the user interacts with it

  • onInit - (function) Triggered when the selectbox is initiated, but before it's built

  • onInputChange - (function) Triggered when someone types in a search box. note: this will do nothing if search is not enabled.

  • onOpen - (function) Triggered when the selectbox is opened

  • onSelect - (function) Triggered when an option selectbox is closed

  • openOnHover - (boolean) replaces click to open action with hover

  • placeholder - (string) Builds a blank option with the placeholder text that is selected by default. This overrides defaultIndex

  • search - (boolean) Determines whether the select box is searchable

  • selectDataOverride - (boolean) If this is true, flounder will ignore sleect box options tags and just apply the passed data

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()
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
  • buildFromUrl( url, callback ) loads data from a remote address, passes it to a callback, then builds the flounder object

  • clickByIndex( index, multiple ) sets the item with the passed index as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This fires the onClick event. A negative index will start counting from the end.

  • clickByText( text, multiple ) sets the item with the passed text as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This fires the onClick event

  • clickByValue( value, multiple ) sets the item with the passed value as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This fires the onClick event

  • deselectAll() deselects all data

  • destroy() removes event listeners, then flounder. this will return the element to it's original state

  • disable( bool ) disables or reenables flounder

  • disableByIndex( index ) disables a flounder option by index. A negative index will start counting from the end.

  • disableByText( text ) disables a flounder option by text

  • disableByValue( value ) disables a flounder option by value

  • enableByIndex( index ) enables a flounder option by index. A negative index will start counting from the end.

  • enableByText( text ) enables a flounder option by text

  • enableByValue( value ) enables a flounder option by value

  • getData( num ) returns the option element and the div element at a specified index as an object { option : option element, div : div element }. If no number is given, it will return all data.

  • getSelected() returns the currently selected option tags in an array

  • getSelectedValues() returns the currently selected values in an array

  • loadDataFromUrl( url, callback ) loads data from a remote address and returns it to a passed callback.

  • props the props set in the initial constructor

  • rebuild( data, props ) rebuilds the select box options with new or altered data. If props are set, this completely rebuilds flounder. Here, props do not necessarily need to include data. If props include data, the data argument can be omitted. Both data and props are optional (rebuild w/ current options).

  • refs contains references to all flounder elements

  • setByIndex( index, multiple ) sets the item with the passed index as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This does not fire the onClick event. A negative index will start counting from the end.

  • setByText( text, multiple ) sets the item with the passed text as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This does not fire the onClick event.

  • setByValue( value, multiple ) sets the item with the passed value as selected. If multiple is true and it is a multi-select box, it is selected additionally. Otherwise it's selected instead. This accepts arrays as well. Without multiple equaling true it will only select the last option. This does not fire the onClick event.

Contributing

We gladly accept and review any pull-requests. Feel free! ❤️

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? [email protected]

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

Releasing

When you release a new verion, commit it to dev (keeps dev upto date), 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

Change Log

0.8.5

  • events

    • fixed a bubbling bug in clickSet
  • api

    • fixed a bug in ie where setByValue wouldn't work as the DOM was still building

0.8.4

  • api
    • fixed a bug in deselectAll where tags would remain

0.8.3

  • search
    • fixed a bug where search would break when only numbers were entered

0.8.2

  • general rolled back the switch from slice to spread

0.8.1

  • release issues...

0.8.0

  • general

    • altered the gitignore to a release branch structure
    • changed node test versions
    • changed packages to better accomodate travis builds
    • moving things to a more es6 sytax
  • build

    • placeholders now have their own class
  • default

    • changed how multipleTags handle defaults
  • css

    • css is now copied to ./dist from ./src directory
  • events

    • added onInputChange
    • changed removeMultipleTags action
  • api

    • console.log is now console.warn

0.7.8

  • api

    • destroy is now much safer
  • jenkins

    • node 0.12 is no longer tested

0.7.7

  • css

    • added 3px padding to selected
  • api

    • destroy now spares surrounding elements

0.7.6

  • css
    • inner arrow pointer-events set to none
    • adjusted padding-right under arrow

0.7.4

  • build

    • disabled select options are now correctly detected
    • moved the build order of the search box and list wrapper for css reasons
  • events

    • click targets are now correctly detected and menu is closed
    • fixed esc / search behaviors
    • fixed click / search behavior
  • css

    • fixed a hover / z-index issue
    • added fuller basic focus, hover, and active indicators

0.7.2

  • api
    • rebuild bug fixed

0.7.1

  • css

    • arrow changed from svg to css
  • build

    • fixed a complex data objects bug

0.7.0

  • build

    • complex data objects are now built correctly
    • added the ability to disable the arrow element
  • wrappers

    • react moved to it's own repo
  • css

    • .flounder__arrow - background colors
    • .flounder__arrow - :hover
    • .flounder__arrow - :active
  • events

    • hover is now javascript based for future expandability
    • openOnHover now available
  • defaults

    • fixed a bug where multiple defaults were being applied
  • api fixed a bug in setDefaultValue concerning index 0

Older Changes

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

About

Style-able dropdown replacement for native dropdowns

Resources

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 92.0%
  • CSS 7.6%
  • HTML 0.4%