Created key bindings for `text` mode
This commit is contained in:
parent
e069d3f0b3
commit
1c37b303b9
|
@ -40,7 +40,10 @@ export default class CodeMode extends TextMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return h('div', {className: 'jsoneditor jsoneditor-mode-code'}, [
|
return h('div', {
|
||||||
|
className: 'jsoneditor jsoneditor-mode-code',
|
||||||
|
onKeyDown: this.handleKeyDown
|
||||||
|
}, [
|
||||||
this.renderMenu(),
|
this.renderMenu(),
|
||||||
|
|
||||||
h('div', {key: 'contents', className: 'jsoneditor-contents'}, h(Ace, {
|
h('div', {key: 'contents', className: 'jsoneditor-contents'}, h(Ace, {
|
||||||
|
|
|
@ -6,6 +6,9 @@ import { parseJSON } from '../utils/jsonUtils'
|
||||||
import { escapeUnicodeChars } from '../utils/stringUtils'
|
import { escapeUnicodeChars } from '../utils/stringUtils'
|
||||||
import { enrichSchemaError, limitErrors } from '../utils/schemaUtils'
|
import { enrichSchemaError, limitErrors } from '../utils/schemaUtils'
|
||||||
import { jsonToData, dataToJson, patchData } from '../jsonData'
|
import { jsonToData, dataToJson, patchData } from '../jsonData'
|
||||||
|
import { createFindKeyBinding } from '../utils/keyBindings'
|
||||||
|
import { KEY_BINDINGS } from '../constants'
|
||||||
|
|
||||||
import ModeButton from './menu/ModeButton'
|
import ModeButton from './menu/ModeButton'
|
||||||
|
|
||||||
const AJV_OPTIONS = {
|
const AJV_OPTIONS = {
|
||||||
|
@ -43,9 +46,17 @@ const AJV_OPTIONS = {
|
||||||
export default class TextMode extends Component {
|
export default class TextMode extends Component {
|
||||||
state: Object
|
state: Object
|
||||||
|
|
||||||
|
keyDownActions = {
|
||||||
|
'format': (event) => this.handleCompact(),
|
||||||
|
'compact': (event) => this.handleFormat()
|
||||||
|
}
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
|
// TODO: make key bindings customizable
|
||||||
|
this.findKeyBinding = createFindKeyBinding(KEY_BINDINGS)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
text: '{}',
|
text: '{}',
|
||||||
compiledSchema: null
|
compiledSchema: null
|
||||||
|
@ -81,7 +92,10 @@ export default class TextMode extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return h('div', {className: 'jsoneditor jsoneditor-mode-text'}, [
|
return h('div', {
|
||||||
|
className: 'jsoneditor jsoneditor-mode-text',
|
||||||
|
onKeyDown: this.handleKeyDown
|
||||||
|
}, [
|
||||||
this.renderMenu(),
|
this.renderMenu(),
|
||||||
|
|
||||||
h('div', {key: 'contents', className: 'jsoneditor-contents'},
|
h('div', {key: 'contents', className: 'jsoneditor-contents'},
|
||||||
|
@ -243,6 +257,16 @@ export default class TextMode extends Component {
|
||||||
// do nothing...
|
// do nothing...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleKeyDown = (event) => {
|
||||||
|
const keyBinding = this.findKeyBinding(event)
|
||||||
|
const action = this.keyDownActions[keyBinding]
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
event.preventDefault()
|
||||||
|
action(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle changed text input in the textarea
|
* handle changed text input in the textarea
|
||||||
* @param {Event} event
|
* @param {Event} event
|
||||||
|
|
|
@ -26,7 +26,8 @@ import {
|
||||||
moveUp, moveDown, moveLeft, moveRight, moveDownSibling, moveHome, moveEnd,
|
moveUp, moveDown, moveLeft, moveRight, moveDownSibling, moveHome, moveEnd,
|
||||||
findNode, selectFind, searchHasFocus, setSelection
|
findNode, selectFind, searchHasFocus, setSelection
|
||||||
} from './utils/domSelector'
|
} from './utils/domSelector'
|
||||||
import { keyComboFromEvent } from '../utils/keyBindings'
|
import { createFindKeyBinding } from '../utils/keyBindings'
|
||||||
|
import { KEY_BINDINGS } from '../constants'
|
||||||
|
|
||||||
import type { JSONData, JSONPatch } from '../types'
|
import type { JSONData, JSONPatch } from '../types'
|
||||||
|
|
||||||
|
@ -40,29 +41,6 @@ const MAX_HISTORY_ITEMS = 1000 // maximum number of undo/redo items to be kept
|
||||||
const SEARCH_DEBOUNCE = 300 // milliseconds
|
const SEARCH_DEBOUNCE = 300 // milliseconds
|
||||||
const SCROLL_DURATION = 400 // milliseconds
|
const SCROLL_DURATION = 400 // milliseconds
|
||||||
|
|
||||||
// TODO: make key bindings configurable
|
|
||||||
const KEY_BINDINGS = {
|
|
||||||
'duplicate': ['Ctrl+D', 'Command+D'],
|
|
||||||
'insert': ['Ctrl+Insert', 'Command+Insert'],
|
|
||||||
'remove': ['Ctrl+Delete', 'Command+Delete'],
|
|
||||||
'expand': ['Ctrl+E', 'Command+E'],
|
|
||||||
'actionMenu': ['Ctrl+M', 'Command+M'],
|
|
||||||
'undo': ['Ctrl+Z', 'Command+Z'],
|
|
||||||
'redo': ['Ctrl+Shift+Z', 'Command+Shift+Z'],
|
|
||||||
'find': ['Ctrl+F', 'Command+F'],
|
|
||||||
'findNext': ['F3', 'Ctrl+G', 'Command+G'],
|
|
||||||
'findPrevious': ['Shift+F3', 'Ctrl+Shift+G', 'Command+Shift+G'],
|
|
||||||
'up': ['Alt+Up', 'Option+Up'],
|
|
||||||
'down': ['Alt+Down', 'Option+Down'],
|
|
||||||
'left': ['Alt+Left', 'Option+Left'],
|
|
||||||
'right': ['Alt+Right', 'Option+Right'],
|
|
||||||
'home': ['Alt+Home', 'Option+Home'],
|
|
||||||
'end': ['Alt+End', 'Option+End'],
|
|
||||||
'openUrl': ['Ctrl+Enter', 'Command+Enter']
|
|
||||||
// TODO: implement Ctrl+Shift+Arrow Up/Down Select multiple fields
|
|
||||||
// TODO: implement Shift+Alt+Arrows Move current field or selected fields up/down/left/right
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TreeMode extends Component {
|
export default class TreeMode extends Component {
|
||||||
id: number
|
id: number
|
||||||
state: Object
|
state: Object
|
||||||
|
@ -88,6 +66,9 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
this.id = Math.round(Math.random() * 1e5) // TODO: create a uuid here?
|
this.id = Math.round(Math.random() * 1e5) // TODO: create a uuid here?
|
||||||
|
|
||||||
|
// TODO: make key bindings customizable
|
||||||
|
this.findKeyBinding = createFindKeyBinding(KEY_BINDINGS)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
data,
|
data,
|
||||||
|
|
||||||
|
@ -113,9 +94,7 @@ export default class TreeMode extends Component {
|
||||||
search: {
|
search: {
|
||||||
text: '',
|
text: '',
|
||||||
active: null // active search result
|
active: null // active search result
|
||||||
},
|
}
|
||||||
|
|
||||||
keyCombos: this.bindingsByCombos (KEY_BINDINGS)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +160,7 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
return h('div', {
|
return h('div', {
|
||||||
className: `jsoneditor jsoneditor-mode-${props.mode}`,
|
className: `jsoneditor jsoneditor-mode-${props.mode}`,
|
||||||
'onKeyDown': this.handleKeyDown,
|
onKeyDown: this.handleKeyDown,
|
||||||
'data-jsoneditor': 'true'
|
'data-jsoneditor': 'true'
|
||||||
}, [
|
}, [
|
||||||
this.renderMenu(searchResults),
|
this.renderMenu(searchResults),
|
||||||
|
@ -276,27 +255,6 @@ export default class TreeMode extends Component {
|
||||||
return h('div', {key: 'menu', className: 'jsoneditor-menu'}, items)
|
return h('div', {key: 'menu', className: 'jsoneditor-menu'}, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn a map with key bindings by name into a map by combo
|
|
||||||
* @param {Object.<String, Array.string>} keyBindings
|
|
||||||
* @return {Object.<String, string>} Returns keyCombos
|
|
||||||
*/
|
|
||||||
bindingsByCombos (keyBindings) {
|
|
||||||
const keyCombos = {}
|
|
||||||
|
|
||||||
Object.keys(keyBindings).forEach ((name) => {
|
|
||||||
keyBindings[name].forEach(combo => keyCombos[combo.toUpperCase()] = name)
|
|
||||||
})
|
|
||||||
|
|
||||||
return keyCombos
|
|
||||||
}
|
|
||||||
|
|
||||||
findKeyBinding = (event) => {
|
|
||||||
const keyCombo = keyComboFromEvent(event)
|
|
||||||
|
|
||||||
return this.state.keyCombos[keyCombo.toUpperCase()] || null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the JSON against the configured JSON schema
|
* Validate the JSON against the configured JSON schema
|
||||||
* Returns an array with the errors when not valid, returns an empty array
|
* Returns an array with the errors when not valid, returns an empty array
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
export const KEY_BINDINGS = {
|
||||||
|
// tree mode
|
||||||
|
'duplicate': ['Ctrl+D', 'Command+D'],
|
||||||
|
'insert': ['Ctrl+Insert', 'Command+Insert'],
|
||||||
|
'remove': ['Ctrl+Delete', 'Command+Delete'],
|
||||||
|
'expand': ['Ctrl+E', 'Command+E'],
|
||||||
|
'actionMenu': ['Ctrl+M', 'Command+M'],
|
||||||
|
'undo': ['Ctrl+Z', 'Command+Z'],
|
||||||
|
'redo': ['Ctrl+Shift+Z', 'Command+Shift+Z'],
|
||||||
|
'find': ['Ctrl+F', 'Command+F'],
|
||||||
|
'findNext': ['F3', 'Ctrl+G', 'Command+G'],
|
||||||
|
'findPrevious': ['Shift+F3', 'Ctrl+Shift+G', 'Command+Shift+G'],
|
||||||
|
'up': ['Alt+Up', 'Option+Up'],
|
||||||
|
'down': ['Alt+Down', 'Option+Down'],
|
||||||
|
'left': ['Alt+Left', 'Option+Left'],
|
||||||
|
'right': ['Alt+Right', 'Option+Right'],
|
||||||
|
'home': ['Alt+Home', 'Option+Home'],
|
||||||
|
'end': ['Alt+End', 'Option+End'],
|
||||||
|
'openUrl': ['Ctrl+Enter', 'Command+Enter'],
|
||||||
|
// TODO: implement Ctrl+Shift+Arrow Up/Down Select multiple fields
|
||||||
|
// TODO: implement Shift+Alt+Arrows Move current field or selected fields up/down/left/right
|
||||||
|
|
||||||
|
// text and code mode
|
||||||
|
'compact': ['Ctrl+\\', 'Command+\\'],
|
||||||
|
'format': ['Ctrl+Shift+\\', 'Command+Shift+\\'],
|
||||||
|
}
|
|
@ -34,6 +34,27 @@ export function keyComboFromEvent (event) {
|
||||||
return combi.join('+')
|
return combi.join('+')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a function which can quickly find a keyBinding from a set of
|
||||||
|
* keyBindings.
|
||||||
|
* @param {Object.<String, String[]>} keyBindings
|
||||||
|
* @return {function} Returns a findKeyBinding function
|
||||||
|
*/
|
||||||
|
export function createFindKeyBinding (keyBindings) {
|
||||||
|
// turn the map with key bindings by name (multiple per binding) into a map by key combo
|
||||||
|
const keyCombos = {}
|
||||||
|
Object.keys(keyBindings).forEach ((name) => {
|
||||||
|
keyBindings[name].forEach(combo => keyCombos[combo.toUpperCase()] = name)
|
||||||
|
})
|
||||||
|
|
||||||
|
return function findKeyBinding (event){
|
||||||
|
const keyCombo = keyComboFromEvent(event)
|
||||||
|
|
||||||
|
return keyCombos[keyCombo.toUpperCase()] || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||||
|
|
||||||
const metaCodes = {
|
const metaCodes = {
|
||||||
|
|
Loading…
Reference in New Issue