rc-select
Advanced tools
Comparing version 3.0.0 to 3.1.0
var React = require('react'); | ||
var Select = require('../'); | ||
var Option = Select.Option; | ||
require('./examples.css'); | ||
require('rc-menu/assets/index.css'); | ||
@@ -6,0 +5,0 @@ require('rc-select/assets/index.css'); |
var React = require('react'); | ||
var Select = require('rc-select'); | ||
var Option = Select.Option; | ||
require('./examples.css'); | ||
require('rc-menu/assets/index.css'); | ||
@@ -16,3 +15,3 @@ require('rc-select/assets/index.css'); | ||
var style = '.rc-select-menu {height:200px;overflow:auto;}'; | ||
var style = '.rc-select-menu {max-height:200px;overflow:auto;}'; | ||
@@ -19,0 +18,0 @@ var c2 = ( |
var React = require('react'); | ||
var Select = require('rc-select'); | ||
var Option = Select.Option; | ||
require('./examples.css'); | ||
require('rc-menu/assets/index.css'); | ||
@@ -6,0 +5,0 @@ require('rc-select/assets/index.css'); |
@@ -14,21 +14,24 @@ /** @jsx React.DOM */ | ||
function isMultipleOrTags(props) { | ||
return props.multiple || props.tags; | ||
} | ||
function noop() { | ||
} | ||
function getKeyFromOptionChild(child) { | ||
function getValueFromOptionChild(child) { | ||
var optionProps = child.props; | ||
var children = optionProps.children; | ||
var ret = child.key || undefined; | ||
if (!ret) { | ||
var ret; | ||
if (optionProps.value !== undefined) { | ||
if (typeof optionProps.value === 'string') { | ||
ret = optionProps.value; | ||
} else if (React.isValidElement(children)) { | ||
if (typeof children.props.children === 'string') { | ||
ret = children.props.children; | ||
} | ||
} | ||
} else if (typeof children === 'string') { | ||
ret = children; | ||
} | ||
if (!ret && !child.props.disabled) { | ||
throw new Error('please set key on Option element!'); | ||
throw new Error('must set value string on Option element!'); | ||
} | ||
return ret; | ||
@@ -39,3 +42,4 @@ } | ||
var ret = { | ||
key: getKeyFromOptionChild(child) | ||
key: getValueFromOptionChild(child), | ||
value: getValueFromOptionChild(child) | ||
}; | ||
@@ -86,9 +90,35 @@ var optionProps = child.props; | ||
_getFilterList(searchText) { | ||
renderFilterOptions() { | ||
var inputValue = this.state.inputValue; | ||
var sel = []; | ||
React.Children.forEach(this.props.children, (child)=> { | ||
if (!searchText || !child.props.disabled && getKeyFromOptionChild(child).indexOf(searchText) > -1) { | ||
var props = this.props; | ||
var childrenKeys = []; | ||
React.Children.forEach(props.children, (child)=> { | ||
if (!inputValue || !child.props.disabled && getValueFromOptionChild(child).indexOf(inputValue) > -1) { | ||
sel.push(child); | ||
} | ||
if (!child.props.disabled) { | ||
childrenKeys.push(getValueFromOptionChild(child)); | ||
} | ||
}); | ||
if (props.tags) { | ||
var value = this.state.value || []; | ||
value = value.filter((v)=> { | ||
return childrenKeys.indexOf(v) === -1 && (!inputValue || v.indexOf(inputValue) > -1); | ||
}); | ||
sel = sel.concat(value.map((v)=> { | ||
return <MenuItem value={v}>{v}</MenuItem>; | ||
})); | ||
if (inputValue) { | ||
var notFindInputItem = sel.every((s)=> { | ||
return getValueFromOptionChild(s) !== inputValue; | ||
}); | ||
if (notFindInputItem) { | ||
sel.unshift(<MenuItem value={inputValue}>{inputValue}</MenuItem>); | ||
} | ||
} | ||
} | ||
if (!sel.length) { | ||
sel = <MenuItem disabled value='NOT_FOUND'>{props.notFoundContent}</MenuItem>; | ||
} | ||
return sel; | ||
@@ -101,3 +131,3 @@ } | ||
}, ()=> { | ||
if (open || this.props.multiple || this.props.combobox) { | ||
if (open || isMultipleOrTags(this.props) || this.props.combobox) { | ||
this.refs.input.getDOMNode().focus(); | ||
@@ -165,3 +195,3 @@ } else { | ||
var value; | ||
if (this.props.multiple) { | ||
if (isMultipleOrTags(this.props)) { | ||
value = this.state.value.concat(); | ||
@@ -176,3 +206,3 @@ value.push(item.props.value); | ||
} | ||
this.props.onChange(this.props.multiple ? value : value[0]); | ||
this.props.onChange(isMultipleOrTags(this.props) ? value : value[0]); | ||
this.setState({ | ||
@@ -190,4 +220,9 @@ value: value, | ||
handleMenuDeselect(key, item) { | ||
this.removeSelected(item.props.value); | ||
handleMenuDeselect(key, item, e) { | ||
if (e.type === 'click') { | ||
this.removeSelected(item.props.value); | ||
} | ||
this.setState({ | ||
inputValue: '' | ||
}); | ||
this.setOpenState(false); | ||
@@ -217,3 +252,3 @@ } | ||
}); | ||
this.props.onChange(this.props.multiple ? value : value[0]); | ||
this.props.onChange(isMultipleOrTags(this.props) ? value : value[0]); | ||
this.setState({ | ||
@@ -227,3 +262,3 @@ value: value | ||
if (this.state.value.length) { | ||
this.props.onChange(this.props.multiple ? [] : undefined); | ||
this.props.onChange(isMultipleOrTags(this.props) ? [] : undefined); | ||
this.setState({ | ||
@@ -240,3 +275,3 @@ value: [], | ||
var menuProps = {}; | ||
if (props.multiple) { | ||
if (isMultipleOrTags(props)) { | ||
menuProps.onDeselect = this.handleMenuDeselect; | ||
@@ -261,3 +296,3 @@ } | ||
activeKey={activeKey} | ||
multiple={props.multiple} | ||
multiple={isMultipleOrTags(props)} | ||
focusable={false} | ||
@@ -271,3 +306,3 @@ {...menuProps} | ||
getTopControlNode(input) { | ||
renderTopControlNode(input) { | ||
var value = this.state.value; | ||
@@ -280,3 +315,3 @@ var prefixCls = this.props.prefixCls; | ||
// single and not combobox, input is inside dropdown | ||
if (!props.combobox && !props.multiple) { | ||
if (!props.combobox && !isMultipleOrTags(props)) { | ||
return <span className={prefixCls + '-selection__rendered'}> | ||
@@ -288,3 +323,3 @@ {value[0]} | ||
var selectedValueNodes; | ||
if (props.multiple) { | ||
if (isMultipleOrTags(props)) { | ||
selectedValueNodes = value.map((v) => { | ||
@@ -304,3 +339,3 @@ return ( | ||
{selectedValueNodes} | ||
{allowClear && !props.multiple ? clear : null} | ||
{allowClear && !isMultipleOrTags(props) ? clear : null} | ||
<li className={joinClasses(prefixCls + '-search', prefixCls + '-search--inline')}>{input}</li> | ||
@@ -335,3 +370,4 @@ </ul> | ||
var props = this.props; | ||
var multiple = props.multiple; | ||
var multiple = isMultipleOrTags(props); | ||
var state = this.state; | ||
var prefixCls = props.prefixCls; | ||
@@ -343,3 +379,3 @@ | ||
onKeyDown={this.handleInputKeyDown} | ||
value={this.state.inputValue} | ||
value={state.inputValue} | ||
className={prefixCls + '-search__field'} | ||
@@ -349,10 +385,6 @@ role="textbox" /> | ||
var children = this._getFilterList(this.state.inputValue); | ||
if (!children.length) { | ||
children = <MenuItem disabled>{props.notFoundContent}</MenuItem>; | ||
} | ||
var ctrlNode = this.getTopControlNode(input); | ||
var children = this.renderFilterOptions(); | ||
var ctrlNode = this.renderTopControlNode(input); | ||
var dropDown; | ||
if (this.state.open) { | ||
if (state.open) { | ||
// single and not combobox, input is inside dropdown | ||
@@ -382,3 +414,3 @@ dropDown = <span key="dropdown" className= {joinClasses(prefixCls + '-dropdown', prefixCls + '-dropdown--below')} tabIndex="-1"> | ||
aria-haspopup="true" | ||
aria-expanded={this.state.open} | ||
aria-expanded={state.open} | ||
{...extraSelectionProps} | ||
@@ -399,2 +431,3 @@ > | ||
multiple: React.PropTypes.bool, | ||
tags: React.PropTypes.bool, | ||
onChange: React.PropTypes.func | ||
@@ -401,0 +434,0 @@ }; |
{ | ||
"name": "rc-select", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "select ui component for react", | ||
@@ -40,3 +40,3 @@ "keywords": [ | ||
"start": "node --harmony node_modules/.bin/rc-server", | ||
"publish": "rc-tools run tag && spm publish && spm doc publish", | ||
"publish": "rc-tools run tag && spm publish", | ||
"lint": "rc-tools run lint", | ||
@@ -43,0 +43,0 @@ "test": "", |
@@ -97,4 +97,10 @@ # rc-select | ||
<td>can select more than one option </td> | ||
</tr> | ||
</tr> | ||
<tr> | ||
<td>tags</td> | ||
<td></td> | ||
<td>false</td> | ||
<td>when tagging is enabled the user can select from pre-existing options or create a new tag by picking the first choice, which is what the user has typed into the search box so far.</td> | ||
</tr> | ||
<tr> | ||
<td>allowClear</td> | ||
@@ -101,0 +107,0 @@ <td></td> |
@@ -111,2 +111,6 @@ /** @jsx React.DOM */ | ||
it('should close on blur', function (done) { | ||
if (navigator.userAgent.indexOf(' Chrome') === -1) { | ||
done(); | ||
return; | ||
} | ||
expect(React.findDOMNode(instance).className.match(/\brc-select-open\b/)).to.be.ok(); | ||
@@ -119,4 +123,45 @@ div.focus(); | ||
}); | ||
}); | ||
describe('when use option tags', function () { | ||
var div; | ||
this.timeout(400000); | ||
beforeEach(function () { | ||
div = document.createElement('div'); | ||
div.tabIndex = 0; | ||
document.body.appendChild(div); | ||
instance = React.render( | ||
<Select tags> | ||
<Option value="1">1</Option> | ||
<Option value="2">2</Option> | ||
</Select>, | ||
div); | ||
}); | ||
afterEach(function () { | ||
React.unmountComponentAtNode(div); | ||
}); | ||
it('should allow user input as tags', function (done) { | ||
if (navigator.userAgent.indexOf(' Chrome') === -1) { | ||
done(); | ||
return; | ||
} | ||
var node = React.findDOMNode(instance.refs.input); | ||
React.addons.TestUtils.Simulate.keyDown( node, {key:"A"} ) | ||
setTimeout(function () { | ||
React.addons.TestUtils.Simulate.keyDown( node, {key:"Enter"} ) | ||
setTimeout(function () { | ||
expect(instance.state.value).to.contain("A"); | ||
}, 100); | ||
done(); | ||
}, 100); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
37046
25
843
182