Implemented highlighting prev/next search result

This commit is contained in:
jos 2016-12-30 14:41:37 +01:00
parent 6ba53f7364
commit fec1bb8f23
3 changed files with 49 additions and 37 deletions

View File

@ -1,12 +1,13 @@
import { createElement as h, Component } from 'react'
import Ajv from 'ajv'
import isEqual from 'lodash/isEqual'
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
import { parseJSON } from '../utils/jsonUtils'
import { enrichSchemaError } from '../utils/schemaUtils'
import {
jsonToData, dataToJson, toDataPath, patchData, pathExists,
expand, addErrors, search, addSearchResults, addFocus
expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult
} from '../jsonData'
import {
duplicate, insert, append, remove,
@ -54,7 +55,7 @@ export default class TreeMode extends Component {
search: {
text: '',
selectedPath: null
active: null // active search result
}
}
}
@ -114,14 +115,8 @@ export default class TreeMode extends Component {
// enrich the data with search results
const searchResults = this.state.search.text ? search(data, this.state.search.text) : null
if (searchResults && searchResults.length > 0) {
const activeSearchResult = searchResults[0] // TODO: store active search result in state
data = addSearchResults(data, searchResults, activeSearchResult)
// TODO: highlight
// data = addFocus(data, searchResults[0]) // TODO: change to using focus from state
if (searchResults) {
data = addSearchResults(data, searchResults, this.state.search.active)
}
// console.log('data', data)
@ -316,19 +311,42 @@ export default class TreeMode extends Component {
/** @private */
handleSearch = (text) => {
this.setState(setIn(this.state, ['search', 'text'], text))
const searchResults = search(this.state.data, text)
this.setState(setIn(this.state, ['search'], {
text,
active: searchResults[0] || null
}))
// TODO: focus on the active result
}
/** @private */
handleNext = () => {
// TODO: implement select next search result
console.log('next search result...')
const searchResults = search(this.state.data, this.state.search.text)
if (searchResults) {
const next = nextSearchResult(searchResults, this.state.search.active)
this.setState(setIn(this.state, ['search', 'active'], next))
// TODO: focus on the active result
}
}
/** @private */
handlePrevious = () => {
// TODO: implement select previous search result
console.log('previous search result...')
const searchResults = search(this.state.data, this.state.search.text)
if (searchResults) {
const previous = previousSearchResult(searchResults, this.state.search.active)
this.setState(setIn(this.state, ['search', 'active'], previous))
// TODO: focus on the active result
}
}
/**

View File

@ -36,14 +36,14 @@ export default class Search extends Component {
type: 'button',
className: 'jsoneditor-search-next',
title: 'Next result',
onClick: this.props.onPrevious
onClick: this.props.onNext
}),
h('input', {
key: 'previous',
type: 'button',
className: 'jsoneditor-search-previous',
title: 'Previous result',
onClick: this.props.onNext
onClick: this.props.onPrevious
})
])
])

View File

@ -9,7 +9,7 @@ import { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutability
import { isObject } from './utils/typeUtils'
import isEqual from 'lodash/isEqual'
import type {SearchResult} from './types'
import type {JSONData, SearchResult} from './types'
/**
* Expand function which will expand all nodes
@ -508,12 +508,8 @@ export function addErrors (data, errors) {
/**
* Search some text in all properties and values
*
* @param {JSONData} data
* @param {string} text
* @return {SearchResult[]} Returns a list with search results
*/
export function search (data, text): SearchResult[] {
export function search (data: JSONData, text: string): SearchResult[] {
let results: SearchResult[] = []
traverse(data, function (value, path) {
@ -593,25 +589,23 @@ export function previousSearchResult (searchResults: SearchResult[], current: Se
/**
* Merge searchResults into the data
*/
export function addSearchResults (data, searchResults: SearchResult[], activeSearchResult: SearchResult) {
export function addSearchResults (data: JSONData, searchResults: SearchResult[], activeSearchResult: SearchResult) {
let updatedData = data
if (searchResults) {
searchResults.forEach(function (searchResult) {
if (searchResult.type === 'value') {
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, dataPath, value)
}
searchResults.forEach(function (searchResult) {
if (searchResult.type === 'value') {
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, dataPath, value)
}
if (searchResult.type === 'property') {
const valueDataPath = toDataPath(data, searchResult.dataPath)
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, propertyDataPath, value)
}
})
}
if (searchResult.type === 'property') {
const valueDataPath = toDataPath(data, searchResult.dataPath)
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, propertyDataPath, value)
}
})
return updatedData
}
@ -623,7 +617,7 @@ export function addSearchResults (data, searchResults: SearchResult[], activeSea
* @param {SearchResult} focusOn
* @return {JSONData} Returns an updated copy of data
*/
export function addFocus (data, focusOn) {
export function addFocus (data: JSONData, focusOn: SearchResult) {
if (focusOn.value) {
const dataPath = toDataPath(data, focusOn.dataPath).concat('focusValue')
return setIn(data, dataPath, true)