diff --git a/.npmignore b/.npmignore
index 9b079aa..0a13a28 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,6 +1,5 @@
demo
dist
-node_modules
src
.gitignore
.jshintrc
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93c30a9..c9fd157 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.3.1 - 2015-01-13
+
+Added: new `buttonActive` property for the `classNames` prop - this will be
+used when one or more options are selected, otherwise `button` will be used.
+
+Changed: `classNames` prop no longer has to provide all properties - defaults
+will be used where not provided.
+
## 0.3.0 - 2015-01-01
Added: double-clicking now adds the selected option to the selection.
diff --git a/README.md b/README.md
index 7ff1885..7bcb120 100644
--- a/README.md
+++ b/README.md
@@ -95,7 +95,9 @@ objects each time the selection is added to.
`className` - class name for the component's `
` container.
-`classNames` - class names for each of the component's child elements.
+`classNames` - class names for each of the component's child elements. See the
+default props below for properties. Defaults will be used for any properties not
+specified via this prop.
`defaultFilter` - default filter text to be applied to the `
`
@@ -122,6 +124,8 @@ the `value` for its ``.
className: 'FilteredMultiSelect',
classNames: {
button: 'FilteredMultiSelect__button',
+ // Used when at least one is selected
+ buttonActive: 'FilteredMultiSelect__button--active',
filter: 'FilteredMultiSelect__filter',
select: 'FilteredMultiSelect__select'
}
diff --git a/demo/app.jsx b/demo/app.jsx
index 127a520..a9f4b1a 100644
--- a/demo/app.jsx
+++ b/demo/app.jsx
@@ -257,6 +257,7 @@ var bootstrapClasses = {
filter: 'form-control'
, select: 'form-control'
, button: 'btn btn btn-block btn-default'
+, buttonActive: 'btn btn btn-block btn-primary'
}
var BasicSelection = React.createClass({
@@ -352,7 +353,12 @@ var AddRemoveSelection = React.createClass({
0
return React.createElement("div", {className: props.className},
React.createElement("input", {
type: "text",
- className: props.classNames.filter,
+ className: this._getClassName('filter'),
placeholder: props.placeholder,
value: state.filter,
onChange: this._onFilterChange,
@@ -188,7 +205,7 @@ var FilteredMultiSelect = React.createClass({displayName: 'FilteredMultiSelect',
),
React.createElement("select", {multiple: true,
ref: "select",
- className: props.classNames.select,
+ className: this._getClassName('select'),
size: props.size,
value: state.selectedValues,
onChange: this._updateSelectedValues,
@@ -199,8 +216,8 @@ var FilteredMultiSelect = React.createClass({displayName: 'FilteredMultiSelect',
})
),
React.createElement("button", {type: "button",
- className: props.classNames.button,
- disabled: state.selectedValues.length === 0,
+ className: hasSelectedOptions ? this._getClassName('buttonActive', 'button') : this._getClassName('button'),
+ disabled: !hasSelectedOptions,
onClick: this._addSelectedToSelection},
this.props.buttonText
)
diff --git a/dist/react-filtered-multiselect.min.js b/dist/react-filtered-multiselect.min.js
index 5a75b7e..c04d0ac 100644
--- a/dist/react-filtered-multiselect.min.js
+++ b/dist/react-filtered-multiselect.min.js
@@ -1,5 +1,5 @@
-/**
- * react-filtered-multiselect 0.3.0 - https://github.com/insin/react-filtered-multiselect
+/*!
+ * react-filtered-multiselect 0.3.1 - https://github.com/insin/react-filtered-multiselect
* MIT Licensed
*/
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.FilteredMultiSelect=e()}}(function(){return function e(t,s,i){function n(l,r){if(!s[l]){if(!t[l]){var p="function"==typeof require&&require;if(!r&&p)return p(l,!0);if(o)return o(l,!0);var a=new Error("Cannot find module '"+l+"'");throw a.code="MODULE_NOT_FOUND",a}var d=s[l]={exports:{}};t[l][0].call(d.exports,function(e){var s=t[l][1][e];return n(s?s:e)},d,d.exports,e,t,s,i)}return s[l].exports}for(var o="function"==typeof require&&require,l=0;li;i++)t?s[e[i][t]]=!0:s[e[i]]=!0;return s}function i(e,t,i){for(var n=[],o=0,l=s(i),r=0,p=e.length,a=i.length;p>r&&a>o;r++)l[e[r][t]]&&(n.push(e[r]),o++);return n}var n="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,o=n.createClass({displayName:"FilteredMultiSelect",propTypes:{buttonText:n.PropTypes.string,className:n.PropTypes.string,classNames:n.PropTypes.object,defaultFilter:n.PropTypes.string,disabled:n.PropTypes.bool,onChange:n.PropTypes.func.isRequired,options:n.PropTypes.array.isRequired,placeholder:n.PropTypes.string,selectedOptions:n.PropTypes.array,size:n.PropTypes.number,textProp:n.PropTypes.string,valueProp:n.PropTypes.string},getDefaultProps:function(){return{buttonText:"Select",className:"FilteredMultiSelect",classNames:{button:"FilteredMultiSelect__button",filter:"FilteredMultiSelect__filter",select:"FilteredMultiSelect__select"},defaultFilter:"",disabled:!1,placeholder:"type to filter",size:6,selectedOptions:[],textProp:"text",valueProp:"value"}},getInitialState:function(){var e=this.props,t=e.defaultFilter,s=e.selectedOptions;return{filter:t,filteredOptions:this._filterOptions(t,s),selectedValues:[]}},componentWillReceiveProps:function(e){(e.options!==this.props.options||e.selectedOptions!==this.props.selectedOptions||e.options.length!=this.props.options.length||e.selectedOptions.length!=this.props.selectedOptions.length)&&this.setState({filteredOptions:this._filterOptions(this.state.filter,e.selectedOptions,e.options)},this._updateSelectedValues)},_filterOptions:function(e,t,i){"undefined"==typeof e&&(e=this.state.filter),"undefined"==typeof t&&(t=this.props.selectedOptions),"undefined"==typeof i&&(i=this.props.options),e=e.toUpperCase();for(var n=this.props,o=n.textProp,l=n.valueProp,r=s(t,l),p=[],a=0,d=i.length;d>a;a++)r[i[a][l]]||e&&-1==i[a][o].toUpperCase().indexOf(e)||p.push(i[a]);return p},_onFilterChange:function(e){var t=e.target.value;this.setState({filter:t,filteredOptions:this._filterOptions(t)},this._updateSelectedValues)},_onFilterKeyPress:function(e){if("Enter"==e.key&&(e.preventDefault(),1==this.state.filteredOptions.length)){var t=this.state.filteredOptions[0],s=this.props.selectedOptions.concat([t]);this.setState({filter:"",selectedValues:[]},function(){this.props.onChange(s)}.bind(this))}},_updateSelectedValues:function(e){for(var t=e?e.target:this.refs.select.getDOMNode(),s=[],i=0,n=t.options.length;n>i;i++)t.options[i].selected&&s.push(t.options[i].value);(e||String(this.state.selectedValues)!=String(s))&&this.setState({selectedValues:s})},_addSelectedToSelection:function(){var e=this.props.selectedOptions.concat(i(this.state.filteredOptions,this.props.valueProp,this.state.selectedValues));this.setState({selectedValues:[]},function(){this.props.onChange(e)}.bind(this))},render:function(){var e=this,t=e.props,s=e.state;return n.createElement("div",{className:t.className},n.createElement("input",{type:"text",className:t.classNames.filter,placeholder:t.placeholder,value:s.filter,onChange:this._onFilterChange,onKeyPress:this._onFilterKeyPress,disabled:t.disabled}),n.createElement("select",{multiple:!0,ref:"select",className:t.classNames.select,size:t.size,value:s.selectedValues,onChange:this._updateSelectedValues,onDoubleClick:this._addSelectedToSelection,disabled:t.disabled},this.state.filteredOptions.map(function(e){return n.createElement("option",{key:e[t.valueProp],value:e[t.valueProp]},e[t.textProp])})),n.createElement("button",{type:"button",className:t.classNames.button,disabled:0===s.selectedValues.length,onClick:this._addSelectedToSelection},this.props.buttonText))}});t.exports=o},{}]},{},[1])(1)});
\ No newline at end of file
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.FilteredMultiSelect=e()}}(function(){return function e(t,s,i){function n(l,r){if(!s[l]){if(!t[l]){var a="function"==typeof require&&require;if(!r&&a)return a(l,!0);if(o)return o(l,!0);var p=new Error("Cannot find module '"+l+"'");throw p.code="MODULE_NOT_FOUND",p}var u=s[l]={exports:{}};t[l][0].call(u.exports,function(e){var s=t[l][1][e];return n(s?s:e)},u,u.exports,e,t,s,i)}return s[l].exports}for(var o="function"==typeof require&&require,l=0;li;i++)t?s[e[i][t]]=!0:s[e[i]]=!0;return s}function i(e,t,i){for(var n=[],o=0,l=s(i),r=0,a=e.length,p=i.length;a>r&&p>o;r++)l[e[r][t]]&&(n.push(e[r]),o++);return n}var n="undefined"!=typeof window?window.React:"undefined"!=typeof global?global.React:null,o={button:"FilteredMultiSelect__button",buttonActive:"FilteredMultiSelect__button--active",filter:"FilteredMultiSelect__filter",select:"FilteredMultiSelect__select"},l=n.createClass({displayName:"FilteredMultiSelect",propTypes:{buttonText:n.PropTypes.string,className:n.PropTypes.string,classNames:n.PropTypes.object,defaultFilter:n.PropTypes.string,disabled:n.PropTypes.bool,onChange:n.PropTypes.func.isRequired,options:n.PropTypes.array.isRequired,placeholder:n.PropTypes.string,selectedOptions:n.PropTypes.array,size:n.PropTypes.number,textProp:n.PropTypes.string,valueProp:n.PropTypes.string},getDefaultProps:function(){return{buttonText:"Select",className:"FilteredMultiSelect",classNames:{},defaultFilter:"",disabled:!1,placeholder:"type to filter",size:6,selectedOptions:[],textProp:"text",valueProp:"value"}},getInitialState:function(){var e=this.props,t=e.defaultFilter,s=e.selectedOptions;return{filter:t,filteredOptions:this._filterOptions(t,s),selectedValues:[]}},componentWillReceiveProps:function(e){(e.options!==this.props.options||e.selectedOptions!==this.props.selectedOptions||e.options.length!=this.props.options.length||e.selectedOptions.length!=this.props.selectedOptions.length)&&this.setState({filteredOptions:this._filterOptions(this.state.filter,e.selectedOptions,e.options)},this._updateSelectedValues)},_getClassName:function(e){if(1==arguments.length)return this.props.classNames[e]||o[e];for(var t=0,s=arguments.length;s>t;t++)if(arguments[t]in this.props.classNames)return this.props.classNames[arguments[t]];return o[e]},_filterOptions:function(e,t,i){"undefined"==typeof e&&(e=this.state.filter),"undefined"==typeof t&&(t=this.props.selectedOptions),"undefined"==typeof i&&(i=this.props.options),e=e.toUpperCase();for(var n=this.props,o=n.textProp,l=n.valueProp,r=s(t,l),a=[],p=0,u=i.length;u>p;p++)r[i[p][l]]||e&&-1==i[p][o].toUpperCase().indexOf(e)||a.push(i[p]);return a},_onFilterChange:function(e){var t=e.target.value;this.setState({filter:t,filteredOptions:this._filterOptions(t)},this._updateSelectedValues)},_onFilterKeyPress:function(e){if("Enter"==e.key&&(e.preventDefault(),1==this.state.filteredOptions.length)){var t=this.state.filteredOptions[0],s=this.props.selectedOptions.concat([t]);this.setState({filter:"",selectedValues:[]},function(){this.props.onChange(s)}.bind(this))}},_updateSelectedValues:function(e){for(var t=e?e.target:this.refs.select.getDOMNode(),s=[],i=0,n=t.options.length;n>i;i++)t.options[i].selected&&s.push(t.options[i].value);(e||String(this.state.selectedValues)!=String(s))&&this.setState({selectedValues:s})},_addSelectedToSelection:function(){var e=this.props.selectedOptions.concat(i(this.state.filteredOptions,this.props.valueProp,this.state.selectedValues));this.setState({selectedValues:[]},function(){this.props.onChange(e)}.bind(this))},render:function(){var e=this,t=e.props,s=e.state,i=s.selectedValues.length>0;return n.createElement("div",{className:t.className},n.createElement("input",{type:"text",className:this._getClassName("filter"),placeholder:t.placeholder,value:s.filter,onChange:this._onFilterChange,onKeyPress:this._onFilterKeyPress,disabled:t.disabled}),n.createElement("select",{multiple:!0,ref:"select",className:this._getClassName("select"),size:t.size,value:s.selectedValues,onChange:this._updateSelectedValues,onDoubleClick:this._addSelectedToSelection,disabled:t.disabled},this.state.filteredOptions.map(function(e){return n.createElement("option",{key:e[t.valueProp],value:e[t.valueProp]},e[t.textProp])})),n.createElement("button",{type:"button",className:i?this._getClassName("buttonActive","button"):this._getClassName("button"),disabled:!i,onClick:this._addSelectedToSelection},this.props.buttonText))}});t.exports=l},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/package.json b/package.json
index a8d7174..f8a7b2d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "react-filtered-multiselect",
"description": "Filtered multi-select React component",
- "version": "0.3.0",
+ "version": "0.3.1",
"main": "./lib/index.js",
"homepage": "https://github.com/insin/react-filtered-multiselect",
"standalone": "FilteredMultiSelect",
diff --git a/src/index.jsx b/src/index.jsx
index f6f4130..35fd839 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -30,6 +30,13 @@ function getItemsByProp(arr, prop, values) {
return items
}
+var DEFAULT_CLASS_NAMES = {
+ button: 'FilteredMultiSelect__button'
+, buttonActive: 'FilteredMultiSelect__button--active'
+, filter: 'FilteredMultiSelect__filter'
+, select: 'FilteredMultiSelect__select'
+}
+
var FilteredMultiSelect = React.createClass({
propTypes: {
buttonText: React.PropTypes.string
@@ -50,11 +57,7 @@ var FilteredMultiSelect = React.createClass({
return {
buttonText: 'Select'
, className: 'FilteredMultiSelect'
- , classNames: {
- button: 'FilteredMultiSelect__button'
- , filter: 'FilteredMultiSelect__filter'
- , select: 'FilteredMultiSelect__select'
- }
+ , classNames: {}
, defaultFilter: ''
, disabled: false
, placeholder: 'type to filter'
@@ -93,6 +96,19 @@ var FilteredMultiSelect = React.createClass({
}
},
+ _getClassName(name) {
+ if (arguments.length == 1) {
+ return this.props.classNames[name] || DEFAULT_CLASS_NAMES[name]
+ }
+
+ for (var i = 0, l = arguments.length; i < l ; i++) {
+ if (arguments[i] in this.props.classNames) {
+ return this.props.classNames[arguments[i]]
+ }
+ }
+ return DEFAULT_CLASS_NAMES[name]
+ },
+
_filterOptions(filter, selectedOptions, options) {
if (typeof filter == 'undefined') {
filter = this.state.filter
@@ -171,10 +187,11 @@ var FilteredMultiSelect = React.createClass({
render() {
var {props, state} = this
+ var hasSelectedOptions = state.selectedValues.length > 0
return
{this.props.buttonText}