Skip to content

Commit 2193fef

Browse files
committed
Put keyboard movement logic in one location
1 parent fc28b9a commit 2193fef

2 files changed

Lines changed: 80 additions & 72 deletions

File tree

src/DataCell.js

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,31 +67,16 @@ export default class DataCell extends PureComponent {
6767
}
6868

6969
handleCommit (value, e) {
70-
this.setState({ value })
7170
const {onChange, onNavigate} = this.props
7271
if (value !== initialData(this.props)) {
72+
this.setState({ value })
7373
onChange(this.props.row, this.props.col, value)
7474
} else {
7575
this.handleRevert()
7676
}
7777
if (e) {
78-
const keyCode = e.which || e.keyCode
79-
switch (keyCode) {
80-
case (ENTER_KEY):
81-
return onNavigate({i: e.shiftKey ? -1 : 1, j: 0})
82-
case (TAB_KEY):
83-
return onNavigate({i: 0, j: e.shiftKey ? -1 : 1})
84-
case (LEFT_KEY):
85-
return onNavigate({i: 0, j: -1})
86-
case (RIGHT_KEY):
87-
return onNavigate({i: 0, j: 1})
88-
case (UP_KEY):
89-
return onNavigate({i: -1, j: 0})
90-
case (DOWN_KEY):
91-
return onNavigate({i: 1, j: 0})
92-
default:
93-
break
94-
}
78+
e.preventDefault()
79+
onNavigate(e, true)
9580
}
9681
}
9782

src/DataSheet.js

Lines changed: 77 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export default class DataSheet extends PureComponent {
3535
this.onContextMenu = this.onContextMenu.bind(this)
3636
this.handleNavigate = this.handleNavigate.bind(this)
3737
this.handleKey = this.handleKey.bind(this).bind(this)
38-
this.handleComponentKey = this.handleComponentKey.bind(this)
3938
this.handleCopy = this.handleCopy.bind(this)
4039
this.handlePaste = this.handlePaste.bind(this)
4140
this.pageClick = this.pageClick.bind(this)
@@ -44,6 +43,9 @@ export default class DataSheet extends PureComponent {
4443
this.isSelected = this.isSelected.bind(this)
4544
this.isEditing = this.isEditing.bind(this)
4645
this.isClearing = this.isClearing.bind(this)
46+
this.handleComponentKey = this.handleComponentKey.bind(this)
47+
48+
this.handleKeyboardCellMovement = this.handleKeyboardCellMovement.bind(this)
4749

4850
this.defaultState = {
4951
start: {},
@@ -131,41 +133,46 @@ export default class DataSheet extends PureComponent {
131133
}
132134
}
133135

134-
handleKeyboardCellMovement (e, {data, start, isEditing, currentCell}) {
135-
if (isEditing) {
136-
return false
137-
}
138-
const hasComponent = currentCell && currentCell.component
139-
const forceComponent = currentCell && currentCell.forceComponent
136+
handleKeyboardCellMovement (e, commit = false) {
137+
const {start, editing} = this.state
138+
const {data} = this.props
139+
const isEditing = editing && !isEmpty(editing)
140+
const currentCell = data[start.i] && data[start.i][start.j]
140141

141-
if (hasComponent && (isEditing || forceComponent)) {
142+
if (isEditing && !commit) {
142143
return false
143144
}
145+
const hasComponent = currentCell && currentCell.component
144146

145147
const keyCode = e.which || e.keyCode
146-
let newLocation = null
147148

148-
if (keyCode === TAB_KEY && !e.shiftKey) {
149-
newLocation = {i: start.i, j: start.j + 1}
150-
newLocation = typeof (data[newLocation.i][newLocation.j]) !== 'undefined' ? newLocation : {i: start.i + 1, j: 0}
149+
if (hasComponent && (isEditing)) { /*
150+
if (keyCode === ESCAPE_KEY) {
151+
e.preventDefault()
152+
this.onRevert()
153+
}
154+
if (keyCode === ENTER_KEY) {
155+
this.handleNavigate(e, {i: e.shiftKey ? -1 : 1, j: 0})
156+
} else if (keyCode === TAB_KEY) {
157+
this.handleNavigate(e, {i: 0, j: e.shiftKey ? -1 : 1}, true)
158+
} */
159+
e.preventDefault()
160+
return
161+
}
162+
163+
if (keyCode === TAB_KEY) {
164+
this.handleNavigate(e, {i: 0, j: e.shiftKey ? -1 : 1}, true)
151165
} else if (keyCode === RIGHT_KEY) {
152-
newLocation = {i: start.i, j: start.j + 1}
153-
} else if (keyCode === LEFT_KEY || ((keyCode === TAB_KEY) && e.shiftKey)) {
154-
newLocation = {i: start.i, j: start.j - 1}
166+
this.handleNavigate(e, {i: 0, j: 1})
167+
} else if (keyCode === LEFT_KEY) {
168+
this.handleNavigate(e, {i: 0, j: -1})
155169
} else if (keyCode === UP_KEY) {
156-
newLocation = {i: start.i - 1, j: start.j}
170+
this.handleNavigate(e, {i: -1, j: 0})
157171
} else if (keyCode === DOWN_KEY) {
158-
newLocation = {i: start.i + 1, j: start.j}
159-
}
160-
161-
if (newLocation && data[newLocation.i] && typeof (data[newLocation.i][newLocation.j]) !== 'undefined') {
162-
this.setState({start: newLocation, end: newLocation, editing: {}})
172+
this.handleNavigate(e, {i: 1, j: 0})
173+
} else if (commit && keyCode === ENTER_KEY) {
174+
this.handleNavigate(e, {i: e.shiftKey ? -1 : 1, j: 0})
163175
}
164-
if (newLocation) {
165-
e.preventDefault()
166-
return true
167-
}
168-
return false
169176
}
170177

171178
getSelectedCells (data, start, end) {
@@ -203,11 +210,12 @@ export default class DataSheet extends PureComponent {
203210
110
204211
].indexOf(keyCode) > -1
205212

206-
if (noCellsSelected || ctrlKeyPressed || this.handleKeyboardCellMovement(e, {data, start, isEditing, currentCell})) {
213+
if (noCellsSelected || ctrlKeyPressed) {
207214
return true
208215
}
209216

210217
if (!isEditing) {
218+
this.handleKeyboardCellMovement(e)
211219
if (deleteKeysPressed) {
212220
// ugly solution brought to you by https://reactjs.org/docs/react-component.html#setstate
213221
// setState in a loop is unreliable
@@ -232,39 +240,54 @@ export default class DataSheet extends PureComponent {
232240
}
233241
}
234242

235-
handleComponentKey (e) {
236-
// handles keyboard events when editing components
237-
const keyCode = e.which || e.keyCode
238-
if ([ENTER_KEY, ESCAPE_KEY, TAB_KEY].includes(keyCode)) {
239-
const {editing} = this.state
240-
if (!isEmpty(editing)) {
241-
const {data} = this.props
242-
const currentCell = data[editing.i][editing.j]
243-
const offset = e.shiftKey ? -1 : 1
244-
if (currentCell && currentCell.component) {
245-
let func = this.onRevert // ESCAPE_KEY
246-
if (keyCode === ENTER_KEY) {
247-
func = () => this.handleNavigate({i: offset, j: 0})
248-
} else if (keyCode === TAB_KEY) {
249-
func = () => this.handleNavigate({i: 0, j: offset})
250-
}
251-
// setTimeout makes sure that component is done handling the event before we take over
252-
setTimeout(func, 1)
243+
handleNavigate (e, offsets, jumpRow) {
244+
if (offsets && (offsets.i || offsets.j)) {
245+
const {start} = this.state
246+
const {data} = this.props
247+
let newLocation = {i: start.i + offsets.i, j: start.j + offsets.j}
248+
const updateLocation = () => {
249+
if (data[newLocation.i] && typeof (data[newLocation.i][newLocation.j]) !== 'undefined') {
250+
this.setState({start: newLocation, end: newLocation, editing: {}})
251+
e.preventDefault()
252+
return true
253+
}
254+
return false
255+
}
256+
if (!updateLocation() && jumpRow) {
257+
if (offsets.j < 0) {
258+
newLocation = {i: start.i - 1, j: data[0].length - 1}
259+
} else {
260+
newLocation = {i: start.i + 1, j: 0}
253261
}
262+
updateLocation()
254263
}
255264
}
256265
}
257266

258-
handleNavigate (offsets) {
259-
if (offsets && (offsets.i || offsets.j)) {
260-
const {start} = this.state
261-
const {data} = this.props
262-
const newLocation = {i: start.i + offsets.i, j: start.j + offsets.j}
263-
if (data[newLocation.i] && typeof (data[newLocation.i][newLocation.j]) !== 'undefined') {
264-
this.setState({start: newLocation, end: newLocation, editing: {}})
267+
handleComponentKey (e) {
268+
// handles keyboard events when editing components
269+
const keyCode = e.which || e.keyCode
270+
if (![ENTER_KEY, ESCAPE_KEY, TAB_KEY].includes(keyCode)) {
271+
return
272+
}
273+
const {editing} = this.state
274+
const {data} = this.props
275+
const isEditing = !isEmpty(editing)
276+
if (isEditing) {
277+
const currentCell = data[editing.i][editing.j]
278+
const offset = e.shiftKey ? -1 : 1
279+
if (currentCell && currentCell.component && !currentCell.forceComponent) {
280+
e.preventDefault()
281+
let func = this.onRevert // ESCAPE_KEY
282+
if (keyCode === ENTER_KEY) {
283+
func = () => this.handleNavigate(e, {i: offset, j: 0})
284+
} else if (keyCode === TAB_KEY) {
285+
func = () => this.handleNavigate(e, {i: 0, j: offset}, true)
286+
}
287+
// setTimeout makes sure that component is done handling the event before we take over
288+
setTimeout(() => { func(); this.dgDom && this.dgDom.focus() }, 1)
265289
}
266290
}
267-
this.dgDom && this.dgDom.focus()
268291
}
269292

270293
onContextMenu (evt, i, j) {
@@ -372,7 +395,7 @@ export default class DataSheet extends PureComponent {
372395
onContextMenu={this.onContextMenu}
373396
onChange={this.onChange}
374397
onRevert={this.onRevert}
375-
onNavigate={this.handleNavigate}
398+
onNavigate={this.handleKeyboardCellMovement}
376399
onKey={this.handleKey}
377400
selected={this.isSelected(i, j)}
378401
editing={this.isEditing(i, j)}

0 commit comments

Comments
 (0)