Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support to sync node expand/collapse operations across editors (#…
…1440)

* Add support to get notified when a JSON node is expanded/collapsed.

  * Added onExpand callback option to be passed while creating JSONEditor
  * The callback is invoked when the expand/collapse is done non-programatically

* Add API to expand/collapse a given node

  * Added JSONEditor.expand() method

* Add example to demostrate syncing expanded nodes across editors

  * Added examples/25_sync_node_expand.html
  • Loading branch information
himanshu520 committed May 31, 2022
1 parent cf15a4a commit d9c3220
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 1 deletion.
32 changes: 32 additions & 0 deletions docs/api.md
Expand Up @@ -98,6 +98,20 @@ Constructs a new JSONEditor.

In order to update css classes when they depend on external state, you can call `editor.refresh()`.

- `{function} onExpand({ path, isExpand, recursive })`

Set a callback function to be invoked when a node is expanded/collapsed (not programtically via APIs). Only applicable when option `mode` is `tree`, `form`, or `view`.

The callback is invoked with an object containing `path`, `isExpand` and `recursive`:

```
{
path: string[],
isExpand: boolean,
recursive: boolean
}
```

- `{function} onEditable({ path, field, value })`

Set a callback function to determine whether individual nodes are editable or read-only. Only applicable when option `mode` is `tree`, `text`, or `code`.
Expand Down Expand Up @@ -679,6 +693,24 @@ Destroy the editor. Clean up DOM, event listeners, and web workers.

Expand all fields. Only applicable for mode 'tree', 'view', and 'form'.

#### `JSONEditor.expand(options)`

Expand/collapse a given JSON node. Only applicable for mode 'tree', 'view' and 'form'.

*`options` fields:*

- `{Array.<String>} path`

Path for the node to expand/collapse

- `{Boolean} isExpand`

Whether to expand the node (else collapse)

- `{Boolean} recursive`

Whether to expand/collapse child nodes recursively

#### `JSONEditor.focus()`

Set focus to the JSONEditor.
Expand Down
87 changes: 87 additions & 0 deletions examples/25_sync_node_expand.html
@@ -0,0 +1,87 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">

<title>JSONEditor | Sync Node Expand</title>

<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>

<style type="text/css">
#jsoneditor-left {
width: 45%;
height: 90%;
float: left;
margin-left: 2%;
}
#jsoneditor-right {
width: 45%;
height: 90%;
float: right;
margin-right: 2%;
}
</style>
</head>
<body>

<div>
<div id="jsoneditor-left"></div>
<div id="jsoneditor-right"></div>
</div>

<script>
const left_json = {
'student_details': {
'name': {
'first_name': 'foo',
'last_name': 'bar'
},
'school': {
'name': 'foo',
'address': 'bar'
},
'contact': '434343',
'age': '39'
},
'marks': [50, 49, 36]
}

const right_json = {
'marks': [50, 49],
'student_details': {
'name': 'foo bar',
'address': {
'street': 'foo',
'city': 'bar',
'zip': '444444'
},
'school': {
'name': 'foo',
'address': 'bar'
},
'age': '39',
'contact': ['434355', '343433', '324343']
}
}

const editor_left = new JSONEditor(document.getElementById('jsoneditor-left'), {
mode: "tree",
onExpand: (options) => {
if (editor_right) {
editor_right.expand(options)
}
}
}, left_json)

const editor_right = new JSONEditor(document.getElementById('jsoneditor-right'), {
mode: "tree",
onExpand: (options) => {
if (editor_left) {
editor_left.expand(options)
}
}
}, right_json)
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion src/js/JSONEditor.js
Expand Up @@ -177,7 +177,7 @@ JSONEditor.prototype.DEBOUNCE_INTERVAL = 150
JSONEditor.VALID_OPTIONS = [
'ajv', 'schema', 'schemaRefs', 'templates',
'ace', 'theme', 'autocomplete',
'onChange', 'onChangeJSON', 'onChangeText',
'onChange', 'onChangeJSON', 'onChangeText', 'onExpand',
'onEditable', 'onError', 'onEvent', 'onModeChange', 'onNodeName', 'onValidate', 'onCreateMenu',
'onSelectionChange', 'onTextSelectionChange', 'onClassName',
'onFocus', 'onBlur',
Expand Down
8 changes: 8 additions & 0 deletions src/js/Node.js
Expand Up @@ -3112,6 +3112,14 @@ export class Node {
frame.appendChild(table)
frame.scrollTop = scrollTop
}

if (typeof this.editor.options.onExpand === 'function') {
this.editor.options.onExpand({
path: this.getPath(),
isExpand: this.expanded,
recursive: recurse
})
}
}

/**
Expand Down
34 changes: 34 additions & 0 deletions src/js/treemode.js
Expand Up @@ -454,6 +454,26 @@ treemode.collapseAll = function () {
}
}

/**
* Expand/collapse a given JSON node.
* @param {Object} [options] Available parameters:
* {Array<String>} [path] Path for the node to expand/collapse.
* {Boolean} [isExpand] Whether to expand the node (else collapse).
* {Boolean} [recursive] Whether to expand/collapse child nodes recursively.
*/
treemode.expand = function (options) {
if (!options) return

const node = this.node ? this.node.findNodeByPath(options.path) : null
if (!node) return

if (options.isExpand) {
node.expand(options.recursive)
} else {
node.collapse(options.recursive)
}
}

/**
* The method onChange is called whenever a field or value is changed, created,
* deleted, duplicated, etc.
Expand Down Expand Up @@ -988,6 +1008,13 @@ treemode._createFrame = function () {
expandAll.title = translate('expandAll')
expandAll.onclick = () => {
editor.expandAll()
if (typeof this.options.onExpand === 'function') {
this.options.onExpand({
path: [],
isExpand: true,
recursive: true
})
}
}
this.menu.appendChild(expandAll)

Expand All @@ -998,6 +1025,13 @@ treemode._createFrame = function () {
collapseAll.className = 'jsoneditor-collapse-all'
collapseAll.onclick = () => {
editor.collapseAll()
if (typeof this.options.onExpand === 'function') {
this.options.onExpand({
path: [],
isExpand: false,
recursive: true
})
}
}
this.menu.appendChild(collapseAll)

Expand Down

0 comments on commit d9c3220

Please sign in to comment.