Implemented key bindings `Alt+Home` and `Alt+End`

This commit is contained in:
jos 2017-07-24 13:39:34 +02:00
parent 633daf6c95
commit e069d3f0b3
2 changed files with 63 additions and 32 deletions

View File

@ -23,7 +23,7 @@ import JSONNodeForm from './JSONNodeForm'
import ModeButton from './menu/ModeButton'
import Search from './menu/Search'
import {
moveUp, moveDown, moveLeft, moveRight, moveDownSibling,
moveUp, moveDown, moveLeft, moveRight, moveDownSibling, moveHome, moveEnd,
findNode, selectFind, searchHasFocus, setSelection
} from './utils/domSelector'
import { keyComboFromEvent } from '../utils/keyBindings'
@ -41,7 +41,6 @@ const SEARCH_DEBOUNCE = 300 // milliseconds
const SCROLL_DURATION = 400 // milliseconds
// TODO: make key bindings configurable
// TODO: implement support for namespaces for key bindings
const KEY_BINDINGS = {
'duplicate': ['Ctrl+D', 'Command+D'],
'insert': ['Ctrl+Insert', 'Command+Insert'],
@ -57,6 +56,8 @@ const KEY_BINDINGS = {
'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
@ -71,6 +72,8 @@ export default class TreeMode extends Component {
'down': (event) => moveDown(event.target),
'left': (event) => moveLeft(event.target),
'right': (event) => moveRight(event.target),
'home': (event) => moveHome(event.target),
'end': (event) => moveEnd(event.target),
'undo': (event) => this.undo(),
'redo': (event) => this.redo(),
'find': (event) => selectFind(event.target),

View File

@ -46,21 +46,10 @@ const INPUT_NAME_RULES = {
* Move the selection to the input field above current selected input
* @param {Element} fromElement
* @param {String} [inputName] Optional name of the input where to move the focus
* @return {boolean} Returns true when successfully moved down
* @return {boolean} Returns true when successfully moved up
*/
export function moveUp (fromElement, inputName = null) {
const prev = findPreviousNode(fromElement)
if (prev) {
if (!lastInputName) {
lastInputName = inputName || getInputName(fromElement)
}
const container = findContentsContainer(fromElement)
const path = parseJSONPointer(prev.getAttribute(PATH_ATTRIBUTE))
return setSelection(container, path, lastInputName)
}
return false
return moveTo(fromElement, findPreviousNode(fromElement), inputName)
}
/**
@ -70,18 +59,7 @@ export function moveUp (fromElement, inputName = null) {
* @return {boolean} Returns true when successfully moved up
*/
export function moveDown (fromElement, inputName = null) {
const next = findNextNode(fromElement)
if (next) {
if (!lastInputName) {
lastInputName = inputName || getInputName(fromElement)
}
const container = findContentsContainer(fromElement)
const path = parseJSONPointer(next.getAttribute(PATH_ATTRIBUTE))
return setSelection(container, path, lastInputName)
}
return false
return moveTo(fromElement, findNextNode(fromElement), inputName)
}
/**
@ -92,18 +70,50 @@ export function moveDown (fromElement, inputName = null) {
* @return {boolean} Returns true when successfully moved up
*/
export function moveDownSibling (fromElement, inputName = null) {
const next = findNextSibling(fromElement)
if (next) {
return moveTo(fromElement, findNextSibling(fromElement), inputName)
}
/**
* Move the selection to the first node
* @param {Element} fromElement
* @param {String} [inputName] Optional name of the input where to move the focus
* @return {boolean} Returns true when successfully moved to home
*/
export function moveHome (fromElement, inputName = null) {
return moveTo(fromElement, findFirstNode(fromElement), inputName)
}
/**
* Move the selection to the last node
* @param {Element} fromElement
* @param {String} [inputName] Optional name of the input where to move the focus
* @return {boolean} Returns true when successfully moved to home
*/
export function moveEnd (fromElement, inputName = null) {
return moveTo(fromElement, findLastNode(fromElement), inputName)
}
/**
* Move from an element to another element
* @param {Element} fromElement
* @param {Element} toElement
* @param {string} [inputName]
* @return {boolean} Returns true when successfully moved
*/
function moveTo (fromElement, toElement, inputName = null) {
if (toElement) {
if (!lastInputName) {
lastInputName = inputName || getInputName(fromElement)
}
const container = findContentsContainer(fromElement)
const path = parseJSONPointer(next.getAttribute(PATH_ATTRIBUTE))
const path = parseJSONPointer(toElement.getAttribute(PATH_ATTRIBUTE))
return setSelection(container, path, lastInputName)
}
else {
return false
}
}
/**
@ -222,6 +232,24 @@ function findNextNode (element) {
return all[index + 1]
}
function findFirstNode (element) {
const container = findContentsContainer(element)
// TODO: is the following querySelectorAll a performance bottleneck?
const all = Array.from(container.querySelectorAll('div.' + NODE_CONTAINER_CLASS_NAME))
return all[0]
}
function findLastNode (element) {
const container = findContentsContainer(element)
// TODO: is the following querySelectorAll a performance bottleneck?
const all = Array.from(container.querySelectorAll('div.' + NODE_CONTAINER_CLASS_NAME))
return all[all.length - 1]
}
function findNextSibling (element) {
const container = findContentsContainer(element)
const node = findBaseNode(element)