Implemented scrolling to active search result
This commit is contained in:
parent
65e868b1c3
commit
d5500bef89
|
@ -0,0 +1,204 @@
|
||||||
|
# Jump.js
|
||||||
|
|
||||||
|
[![Jump.js on NPM](https://img.shields.io/npm/v/jump.js.svg?style=flat-square)](https://www.npmjs.com/package/jump.js)
|
||||||
|
|
||||||
|
A small, modern, dependency-free smooth scrolling library.
|
||||||
|
|
||||||
|
* [Demo Page](http://callmecavs.github.io/jump.js/) (Click the arrows!)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Jump was developed with a modern JavaScript workflow in mind. To use it, it's recommended you have a build system in place that can transpile ES6, and bundle modules. For a minimal boilerplate that fulfills those requirements, check out [outset](https://github.com/callmecavs/outset).
|
||||||
|
|
||||||
|
Follow these steps to get started:
|
||||||
|
|
||||||
|
1. [Install](#install)
|
||||||
|
2. [Import](#import)
|
||||||
|
3. [Call](#call)
|
||||||
|
4. [Review Options](#options)
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
Using NPM, install Jump, and save it to your `package.json` dependencies.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install jump.js --save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import
|
||||||
|
|
||||||
|
Import Jump, naming it according to your preference.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// import Jump
|
||||||
|
|
||||||
|
import jump from 'jump.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Call
|
||||||
|
|
||||||
|
Jump exports a _singleton_, so there's no need to create an instance. Just call it, passing a [target](#target).
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// call Jump, passing a target
|
||||||
|
|
||||||
|
jump('.target')
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the singleton can make an infinite number of jumps.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
All options, **except [target](#target)**, are optional, and have sensible defaults. The defaults are shown below:
|
||||||
|
|
||||||
|
```es6
|
||||||
|
jump('.target', {
|
||||||
|
duration: 1000,
|
||||||
|
offset: 0,
|
||||||
|
callback: undefined,
|
||||||
|
easing: easeInOutQuad,
|
||||||
|
a11y: false
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Explanation of each option follows:
|
||||||
|
|
||||||
|
* [target](#target)
|
||||||
|
* [duration](#duration)
|
||||||
|
* [offset](#offset)
|
||||||
|
* [callback](#callback)
|
||||||
|
* [easing](#easing)
|
||||||
|
* [a11y](#a11y)
|
||||||
|
|
||||||
|
### target
|
||||||
|
|
||||||
|
Scroll _from the current position_ by passing a number of pixels.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// scroll down 100px
|
||||||
|
|
||||||
|
jump(100)
|
||||||
|
|
||||||
|
// scroll up 100px
|
||||||
|
|
||||||
|
jump(-100)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, scroll _to an element_, by passing either:
|
||||||
|
|
||||||
|
* a node, or
|
||||||
|
* a CSS selector
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// passing a node
|
||||||
|
|
||||||
|
const node = document.querySelector('.target')
|
||||||
|
|
||||||
|
jump(node)
|
||||||
|
|
||||||
|
// passing a CSS selector
|
||||||
|
// the element referenced by the selector is determined using document.querySelector
|
||||||
|
|
||||||
|
jump('.target')
|
||||||
|
```
|
||||||
|
|
||||||
|
### duration
|
||||||
|
|
||||||
|
Pass the time the `jump()` takes, in milliseconds.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
jump('.target', {
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, pass a function that returns the duration of the `jump()` in milliseconds. This function is passed the `jump()` `distance`, in `px`, as a parameter.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
jump('.target', {
|
||||||
|
duration: distance => Math.abs(distance)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### offset
|
||||||
|
|
||||||
|
Offset a `jump()`, _only if to an element_, by a number of pixels.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// stop 10px before the top of the element
|
||||||
|
|
||||||
|
jump('.target', {
|
||||||
|
offset: -10
|
||||||
|
})
|
||||||
|
|
||||||
|
// stop 10px after the top of the element
|
||||||
|
|
||||||
|
jump('.target', {
|
||||||
|
offset: 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this option is useful for accommodating `position: fixed` elements.
|
||||||
|
|
||||||
|
### callback
|
||||||
|
|
||||||
|
Pass a function that will be called after the `jump()` has been completed.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
// in both regular and arrow functions, this === window
|
||||||
|
|
||||||
|
jump('.target', {
|
||||||
|
callback: () => console.log('Jump completed!')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### easing
|
||||||
|
|
||||||
|
Easing function used to transition the `jump()`.
|
||||||
|
|
||||||
|
```es6
|
||||||
|
jump('.target', {
|
||||||
|
easing: easeInOutQuad
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
See [easing.js](https://github.com/callmecavs/jump.js/blob/master/src/easing.js) for the definition of `easeInOutQuad`, the default easing function. Credit for this function goes to Robert Penner.
|
||||||
|
|
||||||
|
### a11y
|
||||||
|
|
||||||
|
If enabled, _and scrolling to an element_:
|
||||||
|
|
||||||
|
* add a [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) to, and
|
||||||
|
* [`focus`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) the element
|
||||||
|
|
||||||
|
```es6
|
||||||
|
jump('.target', {
|
||||||
|
a11y: true
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this option is disabled by default because it has _visual implications_ in many browsers. Focusing an element triggers the `:focus` CSS state selector, and is often accompanied by an `outline`.
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
Jump depends on the following browser APIs:
|
||||||
|
|
||||||
|
* [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
|
||||||
|
|
||||||
|
Consequently, it supports the following natively:
|
||||||
|
|
||||||
|
* Chrome 24+
|
||||||
|
* Firefox 23+
|
||||||
|
* Safari 6.1+
|
||||||
|
* Opera 15+
|
||||||
|
* IE 10+
|
||||||
|
* iOS Safari 7.1+
|
||||||
|
* Android Browser 4.4+
|
||||||
|
|
||||||
|
To add support for older browsers, consider including polyfills/shims for the APIs listed above. There are no plans to include any in the library, in the interest of file size.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://opensource.org/licenses/MIT). © 2016 Michael Cavalea
|
||||||
|
|
||||||
|
[![Built With Love](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com)
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Robert Penner's easeInOutQuad
|
||||||
|
|
||||||
|
// find the rest of his easing functions here: http://robertpenner.com/easing/
|
||||||
|
// find them exported for ES6 consumption here: https://github.com/jaxgeller/ez.js
|
||||||
|
|
||||||
|
export default (t, b, c, d) => {
|
||||||
|
t /= d / 2
|
||||||
|
if(t < 1) return c / 2 * t * t + b
|
||||||
|
t--
|
||||||
|
return -c / 2 * (t * (t - 2) - 1) + b
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
import easeInOutQuad from './easing.js'
|
||||||
|
|
||||||
|
const jumper = () => {
|
||||||
|
// private variable cache
|
||||||
|
// no variables are created during a jump, preventing memory leaks
|
||||||
|
|
||||||
|
let container // container element to be scrolled (node)
|
||||||
|
let element // element to scroll to (node)
|
||||||
|
|
||||||
|
let start // where scroll starts (px)
|
||||||
|
let stop // where scroll stops (px)
|
||||||
|
|
||||||
|
let offset // adjustment from the stop position (px)
|
||||||
|
let easing // easing function (function)
|
||||||
|
let a11y // accessibility support flag (boolean)
|
||||||
|
|
||||||
|
let distance // distance of scroll (px)
|
||||||
|
let duration // scroll duration (ms)
|
||||||
|
|
||||||
|
let timeStart // time scroll started (ms)
|
||||||
|
let timeElapsed // time spent scrolling thus far (ms)
|
||||||
|
|
||||||
|
let next // next scroll position (px)
|
||||||
|
|
||||||
|
let callback // to call when done scrolling (function)
|
||||||
|
|
||||||
|
let scrolling // true whilst scrolling (boolean)
|
||||||
|
|
||||||
|
// scroll position helper
|
||||||
|
|
||||||
|
function location() {
|
||||||
|
return container.scrollY || container.pageYOffset || container.scrollTop
|
||||||
|
}
|
||||||
|
|
||||||
|
// element offset helper
|
||||||
|
|
||||||
|
function top(element) {
|
||||||
|
const elementTop = element.getBoundingClientRect().top
|
||||||
|
const containerTop = container.getBoundingClientRect
|
||||||
|
? container.getBoundingClientRect().top
|
||||||
|
: 0
|
||||||
|
|
||||||
|
return elementTop - containerTop + start
|
||||||
|
}
|
||||||
|
|
||||||
|
// scrollTo helper
|
||||||
|
|
||||||
|
function scrollTo(top) {
|
||||||
|
container.scrollTo
|
||||||
|
? container.scrollTo(0, top) // window
|
||||||
|
: container.scrollTop = top // custom container
|
||||||
|
}
|
||||||
|
|
||||||
|
// rAF loop helper
|
||||||
|
|
||||||
|
function loop(timeCurrent) {
|
||||||
|
// store time scroll started, if not started already
|
||||||
|
if(!timeStart) {
|
||||||
|
timeStart = timeCurrent
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine time spent scrolling so far
|
||||||
|
timeElapsed = timeCurrent - timeStart
|
||||||
|
|
||||||
|
// calculate next scroll position
|
||||||
|
next = easing(timeElapsed, start, distance, duration)
|
||||||
|
|
||||||
|
// scroll to it
|
||||||
|
scrollTo(next)
|
||||||
|
|
||||||
|
scrolling = true
|
||||||
|
|
||||||
|
// check progress
|
||||||
|
timeElapsed < duration
|
||||||
|
? requestAnimationFrame(loop) // continue scroll loop
|
||||||
|
: done() // scrolling is done
|
||||||
|
}
|
||||||
|
|
||||||
|
// scroll finished helper
|
||||||
|
|
||||||
|
function done() {
|
||||||
|
// account for rAF time rounding inaccuracies
|
||||||
|
scrollTo(start + distance)
|
||||||
|
|
||||||
|
// if scrolling to an element, and accessibility is enabled
|
||||||
|
if(element && a11y) {
|
||||||
|
// add tabindex indicating programmatic focus
|
||||||
|
element.setAttribute('tabindex', '-1')
|
||||||
|
|
||||||
|
// focus the element
|
||||||
|
element.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it exists, fire the callback
|
||||||
|
if(typeof callback === 'function') {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset time for next jump
|
||||||
|
timeStart = false
|
||||||
|
|
||||||
|
// we're done scrolling
|
||||||
|
scrolling = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
function jump(target, options = {}) {
|
||||||
|
// resolve options, or use defaults
|
||||||
|
duration = options.duration || 1000
|
||||||
|
offset = options.offset || 0
|
||||||
|
callback = options.callback // "undefined" is a suitable default, and won't be called
|
||||||
|
easing = options.easing || easeInOutQuad
|
||||||
|
a11y = options.a11y || false
|
||||||
|
|
||||||
|
// resolve container
|
||||||
|
switch(typeof options.container) {
|
||||||
|
case 'object':
|
||||||
|
// we assume container is an HTML element (Node)
|
||||||
|
container = options.container
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'string':
|
||||||
|
container = document.querySelector(options.container)
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
container = window
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache starting position
|
||||||
|
start = location()
|
||||||
|
|
||||||
|
// resolve target
|
||||||
|
switch(typeof target) {
|
||||||
|
// scroll from current position
|
||||||
|
case 'number':
|
||||||
|
element = undefined // no element to scroll to
|
||||||
|
a11y = false // make sure accessibility is off
|
||||||
|
stop = start + target
|
||||||
|
break
|
||||||
|
|
||||||
|
// scroll to element (node)
|
||||||
|
// bounding rect is relative to the viewport
|
||||||
|
case 'object':
|
||||||
|
element = target
|
||||||
|
stop = top(element)
|
||||||
|
break
|
||||||
|
|
||||||
|
// scroll to element (selector)
|
||||||
|
// bounding rect is relative to the viewport
|
||||||
|
case 'string':
|
||||||
|
element = document.querySelector(target)
|
||||||
|
stop = top(element)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve scroll distance, accounting for offset
|
||||||
|
distance = stop - start + offset
|
||||||
|
|
||||||
|
// resolve duration
|
||||||
|
switch(typeof options.duration) {
|
||||||
|
// number in ms
|
||||||
|
case 'number':
|
||||||
|
duration = options.duration
|
||||||
|
break
|
||||||
|
|
||||||
|
// function passed the distance of the scroll
|
||||||
|
case 'function':
|
||||||
|
duration = options.duration(distance)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the loop if we're not already scrolling
|
||||||
|
if (!scrolling) {
|
||||||
|
requestAnimationFrame(loop)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// reset time for next jump
|
||||||
|
timeStart = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expose only the jump method
|
||||||
|
return jump
|
||||||
|
}
|
||||||
|
|
||||||
|
// export singleton
|
||||||
|
|
||||||
|
const singleton = jumper()
|
||||||
|
|
||||||
|
export default singleton
|
|
@ -1,13 +1,13 @@
|
||||||
// @flow weak
|
// @flow weak
|
||||||
|
|
||||||
import { createElement as h, Component } from 'react'
|
import { createElement as h, Component } from 'react'
|
||||||
//import { Element as ScrollElement } from 'react-scroll'
|
|
||||||
|
|
||||||
import ActionButton from './menu/ActionButton'
|
import ActionButton from './menu/ActionButton'
|
||||||
import AppendActionButton from './menu/AppendActionButton'
|
import AppendActionButton from './menu/AppendActionButton'
|
||||||
import { escapeHTML, unescapeHTML } from '../utils/stringUtils'
|
import { escapeHTML, unescapeHTML } from '../utils/stringUtils'
|
||||||
import { getInnerText, insideRect } from '../utils/domUtils'
|
import { getInnerText, insideRect } from '../utils/domUtils'
|
||||||
import { stringConvert, valueType, isUrl } from '../utils/typeUtils'
|
import { stringConvert, valueType, isUrl } from '../utils/typeUtils'
|
||||||
|
import { compileJSONPointer } from '../jsonData'
|
||||||
|
|
||||||
import type { PropertyData, JSONData, SearchResultStatus } from '../types'
|
import type { PropertyData, JSONData, SearchResultStatus } from '../types'
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ export default class JSONNode extends Component {
|
||||||
|
|
||||||
renderJSONObject ({prop, index, data, options, events}) {
|
renderJSONObject ({prop, index, data, options, events}) {
|
||||||
const childCount = data.props.length
|
const childCount = data.props.length
|
||||||
const node = h('div', {key: 'node', className: 'jsoneditor-node jsoneditor-object'}, [
|
const node = h('div', {name: compileJSONPointer(this.getPath()), key: 'node', className: 'jsoneditor-node jsoneditor-object'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, index, data, options),
|
this.renderProperty(prop, index, data, options),
|
||||||
|
@ -80,7 +80,7 @@ export default class JSONNode extends Component {
|
||||||
|
|
||||||
renderJSONArray ({prop, index, data, options, events}) {
|
renderJSONArray ({prop, index, data, options, events}) {
|
||||||
const childCount = data.items.length
|
const childCount = data.items.length
|
||||||
const node = h('div', {key: 'node', className: 'jsoneditor-node jsoneditor-array'}, [
|
const node = h('div', {name: compileJSONPointer(this.getPath()), key: 'node', className: 'jsoneditor-node jsoneditor-array'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, index, data, options),
|
this.renderProperty(prop, index, data, options),
|
||||||
|
@ -117,7 +117,7 @@ export default class JSONNode extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONValue ({prop, index, data, options}) {
|
renderJSONValue ({prop, index, data, options}) {
|
||||||
return h('div', {className: 'jsoneditor-node'}, [
|
return h('div', {name: compileJSONPointer(this.getPath()), className: 'jsoneditor-node'}, [
|
||||||
this.renderPlaceholder(),
|
this.renderPlaceholder(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, index, data, options),
|
this.renderProperty(prop, index, data, options),
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { createElement as h, Component } from 'react'
|
import { createElement as h, Component } from 'react'
|
||||||
|
import jump from '../assets/jump.js/src/jump'
|
||||||
import Ajv from 'ajv'
|
import Ajv from 'ajv'
|
||||||
|
|
||||||
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
|
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
|
||||||
import { parseJSON } from '../utils/jsonUtils'
|
import { parseJSON } from '../utils/jsonUtils'
|
||||||
import { enrichSchemaError } from '../utils/schemaUtils'
|
import { enrichSchemaError } from '../utils/schemaUtils'
|
||||||
import {
|
import {
|
||||||
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
||||||
expand, expandPath, addErrors,
|
expand, expandPath, addErrors,
|
||||||
search, addSearchResults, nextSearchResult, previousSearchResult
|
search, addSearchResults, nextSearchResult, previousSearchResult,
|
||||||
|
compileJSONPointer
|
||||||
} from '../jsonData'
|
} from '../jsonData'
|
||||||
import {
|
import {
|
||||||
duplicate, insert, append, remove,
|
duplicate, insert, append, remove,
|
||||||
|
@ -34,6 +36,8 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
const data = jsonToData(this.props.data || {}, TreeMode.expandAll, [])
|
const data = jsonToData(this.props.data || {}, TreeMode.expandAll, [])
|
||||||
|
|
||||||
|
this.id = Math.round(Math.random() * 1e5) // TODO: create a uuid here?
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
data,
|
data,
|
||||||
|
|
||||||
|
@ -131,7 +135,12 @@ export default class TreeMode extends Component {
|
||||||
}, [
|
}, [
|
||||||
this.renderMenu(searchResults ? searchResults.length : null),
|
this.renderMenu(searchResults ? searchResults.length : null),
|
||||||
|
|
||||||
h('div', {key: 'contents', className: 'jsoneditor-contents jsoneditor-tree-contents', onClick: this.handleHideMenus},
|
h('div', {
|
||||||
|
key: 'contents',
|
||||||
|
ref: 'contents',
|
||||||
|
className: 'jsoneditor-contents jsoneditor-tree-contents',
|
||||||
|
onClick: this.handleHideMenus, id: this.id
|
||||||
|
},
|
||||||
h('ul', {className: 'jsoneditor-list jsoneditor-root'},
|
h('ul', {className: 'jsoneditor-list jsoneditor-root'},
|
||||||
h(Node, {
|
h(Node, {
|
||||||
data,
|
data,
|
||||||
|
@ -316,14 +325,23 @@ export default class TreeMode extends Component {
|
||||||
/** @private */
|
/** @private */
|
||||||
handleSearch = (text) => {
|
handleSearch = (text) => {
|
||||||
const searchResults = search(this.state.data, text)
|
const searchResults = search(this.state.data, text)
|
||||||
const active = searchResults[0] || null
|
|
||||||
|
if (searchResults.length > 0) {
|
||||||
|
const active = searchResults[0]
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
search: { text, active },
|
search: { text, active },
|
||||||
data: expandPath(this.state.data,active && active.path)
|
data: expandPath(this.state.data, active.path)
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: scroll to the active result
|
// scroll to active search result
|
||||||
|
this.scrollTo(active.path)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
search: { text, active: null }
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
|
@ -337,7 +355,11 @@ export default class TreeMode extends Component {
|
||||||
data: expandPath(this.state.data, next && next.path)
|
data: expandPath(this.state.data, next && next.path)
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: scroll to the active result
|
// scroll to the active result
|
||||||
|
const name = compileJSONPointer(next.path)
|
||||||
|
|
||||||
|
// scroll to the active result
|
||||||
|
this.scrollTo(next.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +374,8 @@ export default class TreeMode extends Component {
|
||||||
data: expandPath(this.state.data, previous && previous.path)
|
data: expandPath(this.state.data, previous && previous.path)
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: scroll to the active result
|
// scroll to the active result
|
||||||
|
this.scrollTo(previous.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,6 +391,21 @@ export default class TreeMode extends Component {
|
||||||
this.emitOnChange (actions, result.revert, result.data)
|
this.emitOnChange (actions, result.revert, result.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll the window vertically to the node with given path
|
||||||
|
* @param {Path} path
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
scrollTo = (path) => {
|
||||||
|
const name = compileJSONPointer(path)
|
||||||
|
const container = this.refs.contents
|
||||||
|
const elem = container.querySelector('div[name="' + name + '"]')
|
||||||
|
|
||||||
|
if (elem) {
|
||||||
|
jump(elem, { container, offset: -100, duration: 400 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit an onChange event when there is a listener for it.
|
* Emit an onChange event when there is a listener for it.
|
||||||
* @param {JSONPatch} patch
|
* @param {JSONPatch} patch
|
||||||
|
|
|
@ -540,6 +540,7 @@ export function addErrors (data, errors) {
|
||||||
export function search (data: JSONData, text: string): DataPointer[] {
|
export function search (data: JSONData, text: string): DataPointer[] {
|
||||||
let results: DataPointer[] = []
|
let results: DataPointer[] = []
|
||||||
|
|
||||||
|
if (text !== '') {
|
||||||
traverse(data, function (value, path) {
|
traverse(data, function (value, path) {
|
||||||
// check property name
|
// check property name
|
||||||
if (path.length > 0) {
|
if (path.length > 0) {
|
||||||
|
@ -562,6 +563,7 @@ export function search (data: JSONData, text: string): DataPointer[] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue