Skip to content

Commit 689753a

Browse files
committed
add option to add a class on focus
1 parent 8e8e152 commit 689753a

File tree

4 files changed

+98
-8
lines changed

4 files changed

+98
-8
lines changed

react-tagsinput.css

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
padding-top: 5px;
77
}
88

9+
.react-tagsinput--focused {
10+
border-color: #a5d24a;
11+
}
12+
913
.react-tagsinput-tag {
1014
background-color: #cde69c;
1115
border-radius: 2px;

react-tagsinput.js

+28-4
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173

174174
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(TagsInput).call(this));
175175

176-
_this.state = { tag: '' };
176+
_this.state = { tag: '', isFocused: false };
177177
_this.focus = _this.focus.bind(_this);
178178
_this.blur = _this.blur.bind(_this);
179179
return _this;
@@ -241,11 +241,13 @@
241241
key: 'focus',
242242
value: function focus() {
243243
this.refs.input.focus();
244+
this.handleOnFocus();
244245
}
245246
}, {
246247
key: 'blur',
247248
value: function blur() {
248249
this.refs.input.blur();
250+
this.handleOnBlur();
249251
}
250252
}, {
251253
key: 'accept',
@@ -318,9 +320,20 @@
318320

319321
this.setState({ tag: tag });
320322
}
323+
}, {
324+
key: 'handleOnFocus',
325+
value: function handleOnFocus() {
326+
this.setState({ isFocused: true });
327+
}
321328
}, {
322329
key: 'handleOnBlur',
323330
value: function handleOnBlur(e) {
331+
this.setState({ isFocused: false });
332+
333+
if (e == null) {
334+
return;
335+
}
336+
324337
if (this.props.addOnBlur) {
325338
this._addTags([e.target.value]);
326339
}
@@ -359,12 +372,20 @@
359372
var renderInput = _props4.renderInput;
360373
var addKeys = _props4.addKeys;
361374
var removeKeys = _props4.removeKeys;
375+
var className = _props4.className;
376+
var focusedClassName = _props4.focusedClassName;
362377

363-
var other = _objectWithoutProperties(_props4, ['value', 'onChange', 'inputProps', 'tagProps', 'renderLayout', 'renderTag', 'renderInput', 'addKeys', 'removeKeys']);
378+
var other = _objectWithoutProperties(_props4, ['value', 'onChange', 'inputProps', 'tagProps', 'renderLayout', 'renderTag', 'renderInput', 'addKeys', 'removeKeys', 'className', 'focusedClassName']);
364379

365-
var tag = this.state.tag;
380+
var _state = this.state;
381+
var tag = _state.tag;
382+
var isFocused = _state.isFocused;
366383

367384

385+
if (isFocused) {
386+
className += ' ' + focusedClassName;
387+
}
388+
368389
var tagComponents = value.map(function (tag, index) {
369390
return renderTag(_extends({ key: index, tag: tag, onRemove: _this2.handleRemove.bind(_this2) }, tagProps));
370391
});
@@ -375,12 +396,13 @@
375396
onPaste: this.handlePaste.bind(this),
376397
onKeyDown: this.handleKeyDown.bind(this),
377398
onChange: this.handleChange.bind(this),
399+
onFocus: this.handleOnFocus.bind(this),
378400
onBlur: this.handleOnBlur.bind(this)
379401
}, this.inputProps()));
380402

381403
return _react2.default.createElement(
382404
'div',
383-
_extends({ ref: 'div', onClick: this.handleClick.bind(this) }, other),
405+
_extends({ ref: 'div', onClick: this.handleClick.bind(this), className: className }, other),
384406
renderLayout(tagComponents, inputComponent)
385407
);
386408
}
@@ -390,6 +412,7 @@
390412
}(_react2.default.Component);
391413

392414
TagsInput.propTypes = {
415+
focusedClassName: _react2.default.PropTypes.string,
393416
addKeys: _react2.default.PropTypes.array,
394417
addOnBlur: _react2.default.PropTypes.bool,
395418
addOnPaste: _react2.default.PropTypes.bool,
@@ -408,6 +431,7 @@
408431
};
409432
TagsInput.defaultProps = {
410433
className: 'react-tagsinput',
434+
focusedClassName: 'react-tagsinput--focused',
411435
addKeys: [9, 13],
412436
addOnBlur: false,
413437
addOnPaste: false,

src/index.js

+23-4
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ function defaultPasteSplit (data) {
5757
class TagsInput extends React.Component {
5858
constructor () {
5959
super()
60-
this.state = {tag: ''}
60+
this.state = {tag: '', isFocused: false}
6161
this.focus = ::this.focus
6262
this.blur = ::this.blur
6363
}
6464

6565
static propTypes = {
66+
focusedClassName: React.PropTypes.string,
6667
addKeys: React.PropTypes.array,
6768
addOnBlur: React.PropTypes.bool,
6869
addOnPaste: React.PropTypes.bool,
@@ -82,6 +83,7 @@ class TagsInput extends React.Component {
8283

8384
static defaultProps = {
8485
className: 'react-tagsinput',
86+
focusedClassName: 'react-tagsinput--focused',
8587
addKeys: [9, 13],
8688
addOnBlur: false,
8789
addOnPaste: false,
@@ -142,10 +144,12 @@ class TagsInput extends React.Component {
142144

143145
focus () {
144146
this.refs.input.focus()
147+
this.handleOnFocus()
145148
}
146149

147150
blur () {
148151
this.refs.input.blur()
152+
this.handleOnBlur()
149153
}
150154

151155
accept () {
@@ -205,7 +209,17 @@ class TagsInput extends React.Component {
205209
this.setState({tag})
206210
}
207211

212+
handleOnFocus () {
213+
this.setState({isFocused: true})
214+
}
215+
208216
handleOnBlur (e) {
217+
this.setState({isFocused: false})
218+
219+
if (e == null) {
220+
return
221+
}
222+
209223
if (this.props.addOnBlur) {
210224
this._addTags([e.target.value])
211225
}
@@ -223,8 +237,12 @@ class TagsInput extends React.Component {
223237

224238
render () {
225239
// eslint-disable-next-line
226-
let {value, onChange, inputProps, tagProps, renderLayout, renderTag, renderInput, addKeys, removeKeys, ...other} = this.props
227-
let {tag} = this.state
240+
let {value, onChange, inputProps, tagProps, renderLayout, renderTag, renderInput, addKeys, removeKeys, className, focusedClassName, ...other} = this.props
241+
let {tag, isFocused} = this.state
242+
243+
if (isFocused) {
244+
className += ' ' + focusedClassName
245+
}
228246

229247
let tagComponents = value.map((tag, index) => {
230248
return renderTag({key: index, tag, onRemove: ::this.handleRemove, ...tagProps})
@@ -236,12 +254,13 @@ class TagsInput extends React.Component {
236254
onPaste: ::this.handlePaste,
237255
onKeyDown: ::this.handleKeyDown,
238256
onChange: ::this.handleChange,
257+
onFocus: ::this.handleOnFocus,
239258
onBlur: ::this.handleOnBlur,
240259
...this.inputProps()
241260
})
242261

243262
return (
244-
<div ref='div' onClick={::this.handleClick} {...other}>
263+
<div ref='div' onClick={::this.handleClick} className={className} {...other}>
245264
{renderLayout(tagComponents, inputComponent)}
246265
</div>
247266
)

test/index.js

+43
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,14 @@ describe("TagsInput", () => {
214214
});
215215

216216
describe("props", () => {
217+
let defaultClassName;
218+
let defaultFocusedClassName;
219+
220+
beforeEach(() => {
221+
defaultClassName = "react-tagsinput";
222+
defaultFocusedClassName = "react-tagsinput--focused";
223+
});
224+
217225
it("should not add a tag twice if onlyUnique is true", () => {
218226
let comp = TestUtils.renderIntoDocument(<TestComponent onlyUnique={true} />);
219227
let tag = randstring();
@@ -311,6 +319,41 @@ describe("TagsInput", () => {
311319
assert.equal(comp.len(), 1, "there should be 1 tags");
312320
});
313321

322+
it("should add a default className to host", () => {
323+
let comp = TestUtils.renderIntoDocument(<TestComponent />);
324+
assert.equal(allClass(comp, defaultClassName).length, 1);
325+
});
326+
327+
it("should add a custom className to host", () => {
328+
let customClassName = "custom-class";
329+
let comp = TestUtils.renderIntoDocument(<TestComponent className={customClassName} />);
330+
assert.equal(allClass(comp, defaultClassName).length, 0);
331+
assert.equal(allClass(comp, customClassName).length, 1);
332+
});
333+
334+
it("should add a default className to host on focus", () => {
335+
let className = `${defaultClassName} ${defaultFocusedClassName}`;
336+
let comp = TestUtils.renderIntoDocument(<TestComponent />);
337+
338+
comp.tagsinput().focus();
339+
assert.equal(allClass(comp, className).length, 1, "on focus");
340+
341+
comp.tagsinput().blur();
342+
assert.equal(allClass(comp, className).length, 0, "on blur");
343+
});
344+
345+
it("should add a custom className to host on focus", () => {
346+
let customFocusedClassName = "custom-focus";
347+
let className = `${defaultClassName} ${customFocusedClassName}`;
348+
let comp = TestUtils.renderIntoDocument(<TestComponent focusedClassName={customFocusedClassName} />);
349+
350+
comp.tagsinput().focus();
351+
assert.equal(allClass(comp, className).length, 1, "on focus");
352+
353+
comp.tagsinput().blur();
354+
assert.equal(allClass(comp, className).length, 0, "on blur");
355+
});
356+
314357
it("should add props to tag", () => {
315358
let comp = TestUtils.renderIntoDocument(<TestComponent tagProps={{className: "test"}} />);
316359
let tag = randstring();

0 commit comments

Comments
 (0)