Skip to content

Commit 31151a8

Browse files
committed
[changed] Move focus handling to Mixin for consistency
1 parent fd6bada commit 31151a8

8 files changed

Lines changed: 145 additions & 151 deletions

File tree

src/Calendar.jsx

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ let Calendar = React.createClass({
105105
require('./mixins/TimeoutMixin'),
106106
require('./mixins/PureRenderMixin'),
107107
require('./mixins/RtlParentContextMixin'),
108-
require('./mixins/AriaDescendantMixin')()
108+
require('./mixins/AriaDescendantMixin')(),
109+
require('./mixins/FocusMixin')({
110+
willHandle() {
111+
if (+this.props.tabIndex === -1)
112+
return false
113+
}
114+
})
109115
],
110116

111117
propTypes,
@@ -188,8 +194,8 @@ let Calendar = React.createClass({
188194
<div {...elementProps}
189195
role='group'
190196
onKeyDown={this._keyDown}
191-
onFocus={this._focus.bind(null, true)}
192-
onBlur ={this._focus.bind(null, false)}
197+
onBlur={this.handleBlur}
198+
onFocus={this.handleFocus}
193199
className={cx(className, 'rw-calendar', 'rw-widget', {
194200
'rw-state-focus': focused,
195201
'rw-state-disabled': disabled,
@@ -275,23 +281,8 @@ let Calendar = React.createClass({
275281
focus() {
276282
if (+this.props.tabIndex > -1)
277283
compat.findDOMNode(this).focus()
278-
279-
//console.log(document.activeElement)
280284
},
281-
282-
@widgetEnabled
283-
_focus(focused, e){
284-
if (+this.props.tabIndex === -1)
285-
return
286-
287-
this.setTimeout('focus', () => {
288-
if( focused !== this.state.focused){
289-
notify(this.props[focused ? 'onFocus' : 'onBlur'], e)
290-
this.setState({ focused })
291-
}
292-
})
293-
},
294-
285+
295286
@widgetEditable
296287
change(date){
297288
if (this.state.view === this.props.initialView){

src/Combobox.jsx

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import GroupableList from './ListGroupable';
1212
import validateList from './util/validateListInterface';
1313
import createUncontrolledWidget from 'uncontrollable';
1414
import { dataItem, dataText, dataIndexOf } from './util/dataHelpers';
15-
import { widgetEditable, widgetEnabled, isDisabled, isReadOnly } from './util/interaction';
15+
import { widgetEditable, isDisabled, isReadOnly } from './util/interaction';
1616
import { instanceId, notify, isFirstFocusedRender } from './util/widgetHelpers';
1717

1818
let defaultSuggest = f => f === true ? 'startsWith' : f ? f : 'eq'
@@ -70,7 +70,16 @@ var ComboBox = React.createClass({
7070
require('./mixins/DataFilterMixin'),
7171
require('./mixins/PopupScrollToMixin'),
7272
require('./mixins/RtlParentContextMixin'),
73-
require('./mixins/AriaDescendantMixin')('input')
73+
require('./mixins/AriaDescendantMixin')('input'),
74+
require('./mixins/FocusMixin')({
75+
willHandle(focused) {
76+
// not suggesting anymore
77+
!focused && this.refs.input.accept()
78+
},
79+
didHandle(focused) {
80+
if (!focused) this.close()
81+
}
82+
})
7483
],
7584

7685
propTypes: propTypes,
@@ -174,8 +183,8 @@ var ComboBox = React.createClass({
174183
{...elementProps}
175184
ref="element"
176185
onKeyDown={this._keyDown}
177-
onFocus={this._focus.bind(null, true)}
178-
onBlur ={this._focus.bind(null, false)}
186+
onBlur={this.handleBlur}
187+
onFocus={this.handleFocus}
179188
tabIndex={'-1'}
180189
className={cx(className, 'rw-combobox', 'rw-widget', {
181190
'rw-state-focus': focused,
@@ -287,22 +296,6 @@ var ComboBox = React.createClass({
287296
this.refs.input.focus()
288297
},
289298

290-
@widgetEnabled
291-
_focus(focused, e){
292-
293-
!focused && this.refs.input.accept() //not suggesting anymore
294-
295-
this.setTimeout('focus', () => {
296-
297-
if( !focused) this.close()
298-
299-
if( focused !== this.state.focused) {
300-
notify(this.props[focused ? 'onFocus' : 'onBlur'], e)
301-
this.setState({ focused: focused })
302-
}
303-
})
304-
},
305-
306299
@widgetEditable
307300
_keyDown(e){
308301
var self = this

src/DateTimePicker.jsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import DateInput from './DateInput';
1616
import Btn from './WidgetButton';
1717
import CustomPropTypes from './util/propTypes';
1818
import createUncontrolledWidget from 'uncontrollable';
19-
import { widgetEditable, widgetEnabled } from './util/interaction';
19+
import { widgetEditable } from './util/interaction';
2020
import { instanceId, notify, isFirstFocusedRender } from './util/widgetHelpers';
2121

2222
let { calendarViews: views, datePopups: popups } = constants;
@@ -90,6 +90,11 @@ var DateTimePicker = React.createClass({
9090
require('./mixins/PureRenderMixin'),
9191
require('./mixins/PopupScrollToMixin'),
9292
require('./mixins/RtlParentContextMixin'),
93+
require('./mixins/FocusMixin')({
94+
didHandle(focused) {
95+
if (!focused) this.close()
96+
}
97+
}),
9398
require('./mixins/AriaDescendantMixin')('valueInput', function(key, id){
9499
var { open } = this.props
95100
, current = this.ariaActiveDescendant()
@@ -168,8 +173,8 @@ var DateTimePicker = React.createClass({
168173
tabIndex={'-1'}
169174
onKeyDown={this._keyDown}
170175
onKeyPress={this._keyPress}
171-
onFocus={this._focus.bind(null, true)}
172-
onBlur={this._focus.bind(null, false)}
176+
onBlur={this.handleBlur}
177+
onFocus={this.handleFocus}
173178
className={cx(className, 'rw-datetimepicker', 'rw-widget', {
174179
'rw-state-focus': focused,
175180
'rw-state-disabled': disabled,
@@ -356,19 +361,6 @@ var DateTimePicker = React.createClass({
356361
this.refs.timePopup._keyPress(e)
357362
},
358363

359-
@widgetEnabled
360-
_focus(focused, e){
361-
362-
this.setTimeout('focus', () => {
363-
if (!focused) this.close()
364-
365-
if (focused !== this.state.focused){
366-
notify(this.props[focused ? 'onFocus' : 'onBlur'], e)
367-
this.setState({ focused })
368-
}
369-
})
370-
},
371-
372364
focus(){
373365
if (activeElement() !== compat.findDOMNode(this.refs.valueInput))
374366
this.refs.valueInput.focus()

src/DropdownList.jsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ var DropdownList = React.createClass({
6969
require('./mixins/DataFilterMixin'),
7070
require('./mixins/PopupScrollToMixin'),
7171
require('./mixins/RtlParentContextMixin'),
72-
require('./mixins/AriaDescendantMixin')()
72+
require('./mixins/AriaDescendantMixin')(),
73+
require('./mixins/FocusMixin')({
74+
didHandle(focused) {
75+
if (!focused) this.close()
76+
}
77+
})
7378
],
7479

7580
propTypes: propTypes,
@@ -160,8 +165,8 @@ var DropdownList = React.createClass({
160165
onKeyDown={this._keyDown}
161166
onKeyPress={this._keyPress}
162167
onClick={this._click}
163-
onFocus={this._focus.bind(null, true)}
164-
onBlur ={this._focus.bind(null, false)}
168+
onBlur={this.handleBlur}
169+
onFocus={this.handleFocus}
165170
className={cx(className, 'rw-dropdownlist', 'rw-widget', {
166171
'rw-state-disabled': disabled,
167172
'rw-state-readonly': readOnly,
@@ -231,19 +236,6 @@ var DropdownList = React.createClass({
231236
)
232237
},
233238

234-
@widgetEnabled
235-
_focus(focused, e){
236-
237-
this.setTimeout('focus', () => {
238-
if (!focused) this.close()
239-
240-
if (focused !== this.state.focused) {
241-
notify(this.props[focused ? 'onFocus' : 'onBlur'], e)
242-
this.setState({ focused: focused })
243-
}
244-
})
245-
},
246-
247239
@widgetEditable
248240
_onSelect(data){
249241
this.close()

src/Multiselect.jsx

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import GroupableList from './ListGroupable';
1010
import validateList from './util/validateListInterface';
1111
import createUncontrolledWidget from 'uncontrollable';
1212
import { dataItem, dataText, valueMatcher } from './util/dataHelpers';
13-
import { widgetEditable, widgetEnabled } from './util/interaction';
13+
import { widgetEditable } from './util/interaction';
1414
import { instanceId, notify, isFirstFocusedRender } from './util/widgetHelpers';
1515

1616
var compatCreate = (props, msgs) => typeof msgs.createNew === 'function'
@@ -76,6 +76,20 @@ var Multiselect = React.createClass({
7676
require('./mixins/DataFilterMixin'),
7777
require('./mixins/PopupScrollToMixin'),
7878
require('./mixins/RtlParentContextMixin'),
79+
require('./mixins/FocusMixin')({
80+
willHandle(focused) {
81+
focused && this.focus()
82+
},
83+
didHandle(focused) {
84+
if (!focused) this.close()
85+
86+
if (!focused && this.refs.tagList)
87+
this.setState({ focusedTag: null })
88+
89+
if (focused && !this.props.open)
90+
this.open()
91+
}
92+
}),
7993
require('./mixins/AriaDescendantMixin')('input', function(key, id){
8094
let { ariaActiveDescendantKey: myKey } = this.props;
8195

@@ -191,9 +205,9 @@ var Multiselect = React.createClass({
191205
ref="element"
192206
id={instanceId(this)}
193207
onKeyDown={this._keyDown}
194-
onFocus={this._focus.bind(null, true)}
195-
onBlur ={this._focus.bind(null, false)}
196-
onTouchEnd={this._focus.bind(null, true)}
208+
onBlur={this.handleBlur}
209+
onFocus={this.handleFocus}
210+
onTouchEnd={this.handleFocus}
197211
tabIndex={'-1'}
198212
className={cx(className, 'rw-widget', 'rw-multiselect', {
199213
'rw-state-focus': focused,
@@ -255,9 +269,8 @@ var Multiselect = React.createClass({
255269
onKeyDown={this._searchKeyDown}
256270
onKeyUp={this._searchgKeyUp}
257271
onChange={this._typing}
258-
onFocus={this._inputFocus}
259-
onClick={this._inputFocus}
260-
onTouchEnd={this._inputFocus}
272+
onClick={this.handleInputInteraction}
273+
onTouchEnd={this.handleInputInteraction}
261274
/>
262275
</div>
263276
<Popup {...popupProps}
@@ -309,54 +322,32 @@ var Multiselect = React.createClass({
309322
return this.state.processedData
310323
},
311324

312-
_delete(value){
313-
this._focus(true)
325+
_delete(value) {
326+
this.focus()
314327
this.change(
315328
this.state.dataItems.filter( d => d !== value))
316329
},
317330

318-
_inputFocus(){
319-
this._focus(true)
320-
!this.props.open && this.open()
321-
},
322-
323-
@widgetEnabled
324-
_focus(focused, e){
325-
if (this.props.disabled === true )
326-
return
327-
328-
if(focused) this.refs.input.focus()
329-
330-
this.setTimeout('focus', () => {
331-
if(!focused)
332-
this.refs.tagList && this.setState({ focusedTag: null })
333-
334-
if(focused !== this.state.focused) {
335-
focused
336-
? this.open()
337-
: this.close();
338-
339-
notify(this.props[focused ? 'onFocus' : 'onBlur'], e)
340-
this.setState({ focused: focused })
341-
}
342-
})
343-
},
344-
345-
_searchKeyDown(e){
331+
_searchKeyDown(e) {
346332
if (e.key === 'Backspace' && e.target.value && !this._deletingText)
347333
this._deletingText = true
348334
},
349335

350-
_searchgKeyUp(e){
336+
_searchgKeyUp(e) {
351337
if (e.key === 'Backspace' && this._deletingText)
352338
this._deletingText = false
353339
},
354340

355-
_typing(e){
341+
_typing(e) {
356342
notify(this.props.onSearch, [ e.target.value ])
357343
this.open()
358344
},
359345

346+
@widgetEditable
347+
handleInputInteraction() {
348+
this.open()
349+
},
350+
360351
@widgetEditable
361352
_onSelect(data){
362353

@@ -371,7 +362,7 @@ var Multiselect = React.createClass({
371362
this.change(this.state.dataItems.concat(data))
372363

373364
this.close()
374-
this._focus(true)
365+
this.focus()
375366
},
376367

377368
@widgetEditable
@@ -384,7 +375,7 @@ var Multiselect = React.createClass({
384375
&& notify(this.props.onSearch, [ '' ])
385376

386377
this.close()
387-
this._focus(true)
378+
this.focus()
388379
},
389380

390381
@widgetEditable
@@ -461,8 +452,12 @@ var Multiselect = React.createClass({
461452
notify(this.props.onSearch, [ '' ])
462453
},
463454

464-
open(){
465-
if (!(this.props.disabled === true || this.props.readOnly === true))
455+
focus() {
456+
this.refs.input.focus()
457+
},
458+
459+
open() {
460+
if (!this.props.open)
466461
notify(this.props.onToggle, true)
467462
},
468463

@@ -521,4 +516,4 @@ function msgs(msgs){
521516
}
522517

523518
export default createUncontrolledWidget(Multiselect
524-
, { open: 'onToggle', value: 'onChange', searchTerm: 'onSearch' });
519+
, { open: 'onToggle', value: 'onChange', searchTerm: 'onSearch' }, ['focus']);

0 commit comments

Comments
 (0)