Skip to content

Commit

Permalink
support tags at 3.1.0. Fixes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
yiminghe committed Mar 23, 2015
1 parent 6ef6012 commit 045ab64
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 56 deletions.
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# History
----

## 3.1.0 / 2015-03-23

`new` [#2](https://github.com/react-component/select/pull/2) support tags config
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ React.render(c, container);
<td></td>
<td>false</td>
<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>
<td></td>
Expand Down
10 changes: 8 additions & 2 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
margin: 0;
position: relative;
vertical-align: middle;

ul,li {
margin: 0;
padding: 0;
list-style: none;
}

> ul > li > a {
padding: 0;
background-color: #fff;
Expand Down Expand Up @@ -50,7 +57,6 @@
padding-left: 8px;
padding-right: 20px;
text-overflow: ellipsis;

color: #444;
line-height: 28px;
}
Expand All @@ -77,8 +83,8 @@
.rc-select-selection__rendered {
display: inline-block;
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
padding-left: 8px;
}

.rc-select-selection__clear {
Expand Down
1 change: 0 additions & 1 deletion examples/combobox.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var React = require('react');
var Select = require('../');
var Option = Select.Option;
require('./examples.css');
require('rc-menu/assets/index.css');
require('rc-select/assets/index.css');
var style = {
Expand Down
18 changes: 0 additions & 18 deletions examples/examples.less

This file was deleted.

3 changes: 1 addition & 2 deletions examples/multiple.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var React = require('react');
var Select = require('rc-select');
var Option = Select.Option;
require('./examples.css');
require('rc-menu/assets/index.css');
require('rc-select/assets/index.css');
var children = [];
Expand All @@ -13,7 +12,7 @@ function handleChange(value) {
console.log('selected ' + value);
}

var style = '.rc-select-menu {height:200px;overflow:auto;}';
var style = '.rc-select-menu {max-height:200px;overflow:auto;}';

var c2 = (
<div>
Expand Down
1 change: 0 additions & 1 deletion examples/single.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var React = require('react');
var Select = require('rc-select');
var Option = Select.Option;
require('./examples.css');
require('rc-menu/assets/index.css');
require('rc-select/assets/index.css');
function handleChange(value) {
Expand Down
5 changes: 2 additions & 3 deletions examples/tags.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var React = require('react');
var Select = require('rc-select');
var Option = Select.Option;
require('./examples.css');
require('rc-menu/assets/index.css');
require('rc-select/assets/index.css');
var children = [];
Expand All @@ -13,11 +12,11 @@ function handleChange(value) {
console.log('selected ' + value);
}

var style = '.rc-select-menu {height:200px;overflow:auto;}';
var style = '.rc-select-menu {max-height:200px;overflow:auto;}';

var c2 = (
<div>
<h1>multiple select(scroll the menu)</h1>
<h1>tags select(scroll the menu)</h1>
<div style={{width: 300}}>
<style>
{style}
Expand Down
78 changes: 51 additions & 27 deletions lib/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,35 @@ var KeyCode = rcUtil.KeyCode;
var Menu = require('rc-menu');
var MenuItem = Menu.Item;

function isMultipleOrTags(props){
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;
}

function getPropsFromOption(child) {
var ret = {
key: getKeyFromOptionChild(child)
key: getValueFromOptionChild(child),
value: getValueFromOptionChild(child)
};
var optionProps = child.props;
for (var i in optionProps) {
Expand Down Expand Up @@ -85,13 +85,39 @@ class Select extends React.Component {
});
}

_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;
}

Expand Down Expand Up @@ -185,7 +211,10 @@ class Select extends React.Component {
}
}

handleMenuDeselect() {
handleMenuDeselect(key, item, e) {
if (e.type === 'click') {
this.removeSelected(item.props.value);
}
this.setState({
inputValue: ''
});
Expand Down Expand Up @@ -263,7 +292,7 @@ class Select extends React.Component {
</Menu>;
}

getTopControlNode(input) {
renderTopControlNode(input) {
var value = this.state.value;
var prefixCls = this.props.prefixCls;
var allowClear = this.props.allowClear;
Expand Down Expand Up @@ -323,28 +352,23 @@ class Select extends React.Component {

render() {
var props = this.props;
var multiple = isMultipleOrTags(this.props);
var multiple = isMultipleOrTags(props);
var state = this.state;
var prefixCls = props.prefixCls;

var input = (
<input ref="input"
onChange={this.handleInputChange}
onKeyDown={this.handleInputKeyDown}
value={this.state.inputValue}
value={state.inputValue}
className={prefixCls + '-search__field'}
role="textbox" />
);

var children = this._getFilterList(this.state.inputValue);
if (!children.length) {
children = !this.props.tags ?
<MenuItem disabled>{props.notFoundContent}</MenuItem> :
<MenuItem value={this.state.inputValue}>{this.state.inputValue}</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
dropDown = <span key="dropdown" className= {joinClasses(prefixCls + '-dropdown', prefixCls + '-dropdown--below')} tabIndex="-1">
{multiple || props.combobox ? null : <span className={joinClasses(prefixCls + '-search', prefixCls + '-search--dropdown')}>{input}</span>}
Expand All @@ -369,7 +393,7 @@ class Select extends React.Component {
aria-autocomplete="list"
onClick={this.handleClick}
aria-haspopup="true"
aria-expanded={this.state.open}
aria-expanded={state.open}
{...extraSelectionProps}
>
{ctrlNode}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rc-select",
"version": "3.0.0",
"version": "3.1.0",
"description": "select ui component for react",
"keywords": [
"react",
Expand Down

0 comments on commit 045ab64

Please sign in to comment.