0
# Tree Operations
1
2
Interactive tree editing capabilities including node manipulation, selection management, expansion control, and visual operations for tree, view, and form modes.
3
4
## Capabilities
5
6
### Expand All Nodes
7
8
Expand all collapsible nodes in the tree to show the complete data structure.
9
10
```javascript { .api }
11
/**
12
* Expand all fields in the tree
13
* Only applicable for tree, view, and form modes
14
*/
15
expandAll(): void;
16
```
17
18
**Usage Example:**
19
20
```javascript
21
// Expand all nodes to show full structure
22
editor.expandAll();
23
```
24
25
### Collapse All Nodes
26
27
Collapse all expanded nodes to show only the top-level structure.
28
29
```javascript { .api }
30
/**
31
* Collapse all fields in the tree
32
* Only applicable for tree, view, and form modes
33
*/
34
collapseAll(): void;
35
```
36
37
**Usage Example:**
38
39
```javascript
40
// Collapse all nodes for compact view
41
editor.collapseAll();
42
```
43
44
### Expand Specific Node
45
46
Expand or collapse a specific node at a given path with optional recursion.
47
48
```javascript { .api }
49
/**
50
* Expand or collapse a specific JSON node
51
* @param options - Expansion configuration
52
*/
53
expand(options: ExpandOptions): void;
54
55
interface ExpandOptions {
56
/** Path to the node to expand/collapse */
57
path: (string | number)[];
58
59
/** True to expand, false to collapse */
60
isExpand: boolean;
61
62
/** Apply to child nodes recursively (optional) */
63
recursive?: boolean;
64
65
/** Also expand/collapse all nodes in the path (optional) */
66
withPath?: boolean;
67
}
68
```
69
70
**Usage Example:**
71
72
```javascript
73
// Expand a specific node
74
editor.expand({
75
path: ['users', 0, 'address'],
76
isExpand: true
77
});
78
79
// Collapse a node and all its children
80
editor.expand({
81
path: ['data'],
82
isExpand: false,
83
recursive: true
84
});
85
86
// Expand a node and ensure its path is visible
87
editor.expand({
88
path: ['config', 'database', 'settings'],
89
isExpand: true,
90
withPath: true
91
});
92
```
93
94
### Set Node Selection
95
96
Set selection for a range of nodes in the tree, supporting both single and multi-node selection.
97
98
```javascript { .api }
99
/**
100
* Set selection for a range of nodes
101
* @param start - Path to start node (optional)
102
* @param end - Path to end node (optional)
103
*/
104
setSelection(start?: (string | number)[], end?: (string | number)[]): void;
105
```
106
107
**Usage Example:**
108
109
```javascript
110
// Select a single node
111
editor.setSelection(['users', 0, 'name']);
112
113
// Select a range of nodes
114
editor.setSelection(['users', 0], ['users', 2]);
115
116
// Clear selection
117
editor.setSelection();
118
```
119
120
### Get Current Selection
121
122
Retrieve the currently selected nodes in the tree.
123
124
```javascript { .api }
125
/**
126
* Get the current selected nodes
127
* @returns Object with start and end selection points
128
*/
129
getSelection(): { start: SerializableNode; end: SerializableNode };
130
131
interface SerializableNode {
132
/** Value of the selected node */
133
value: any;
134
135
/** Path to the selected node */
136
path: (string | number)[];
137
}
138
```
139
140
**Usage Example:**
141
142
```javascript
143
const selection = editor.getSelection();
144
145
if (selection.start) {
146
console.log('Selection start:', selection.start.path);
147
console.log('Start value:', selection.start.value);
148
}
149
150
if (selection.end && selection.end.path !== selection.start?.path) {
151
console.log('Multi-node selection to:', selection.end.path);
152
}
153
```
154
155
### Get Nodes by Range
156
157
Get all nodes within a specified range, useful for batch operations on selected content.
158
159
```javascript { .api }
160
/**
161
* Get a list of all nodes within a specified range
162
* @param start - Path to the first node in range
163
* @param end - Path to the last node in range
164
* @returns Array of all nodes in the range
165
*/
166
getNodesByRange(start: (string | number)[], end: (string | number)[]): SerializableNode[];
167
```
168
169
### Search Tree Content
170
171
Search for text within all nodes in the tree and return matching results.
172
173
```javascript { .api }
174
/**
175
* Search for text in all nodes of the tree
176
* @param text - Text to search for
177
* @returns Array of search result objects with node information
178
*/
179
search(text: string): SearchResult[];
180
181
interface SearchResult {
182
/** Path to the node containing the match */
183
path: (string | number)[];
184
185
/** Field name where the match was found */
186
field: string;
187
188
/** Value containing the match */
189
value: any;
190
191
/** Node object reference */
192
node: any;
193
}
194
```
195
196
**Usage Example:**
197
198
```javascript
199
// Search for text in all nodes
200
const results = editor.search("example");
201
202
results.forEach(result => {
203
console.log(`Found "${result.field}" at path: ${result.path.join('.')}`);
204
console.log(`Value: ${result.value}`);
205
});
206
207
// Search for partial matches
208
const partialResults = editor.search("mail"); // Finds "email", "mailbox", etc.
209
210
// Navigate to first search result
211
if (results.length > 0) {
212
editor.setSelection(results[0].path);
213
214
// Expand path to make result visible
215
editor.expand({
216
path: results[0].path,
217
isExpand: true,
218
withPath: true
219
});
220
}
221
```
222
223
**Usage Example:**
224
225
```javascript
226
// Get all nodes in a range
227
const nodes = editor.getNodesByRange(['users', 0], ['users', 5]);
228
229
nodes.forEach(node => {
230
console.log(`Node at ${node.path.join('.')}: ${node.value}`);
231
});
232
233
// Process nodes in selection range
234
const selection = editor.getSelection();
235
if (selection.start && selection.end) {
236
const selectedNodes = editor.getNodesByRange(
237
selection.start.path,
238
selection.end.path
239
);
240
241
// Perform batch operation
242
selectedNodes.forEach(node => {
243
// Process each selected node
244
});
245
}
246
```
247
248
### Selection Change Events
249
250
Handle selection changes with event callbacks to respond to user interactions.
251
252
```javascript { .api }
253
/**
254
* Selection change callback in editor options
255
*/
256
interface SelectionCallbacks {
257
onSelectionChange?: (start?: SerializableNode, end?: SerializableNode) => void;
258
}
259
```
260
261
**Usage Example:**
262
263
```javascript
264
const options = {
265
mode: "tree",
266
onSelectionChange: (start, end) => {
267
if (!start) {
268
console.log("Selection cleared");
269
return;
270
}
271
272
const pathStr = start.path.join('.');
273
console.log(`Selected: ${pathStr} = ${JSON.stringify(start.value)}`);
274
275
if (end && end.path !== start.path) {
276
const endPathStr = end.path.join('.');
277
console.log(`Multi-selection to: ${endPathStr}`);
278
}
279
280
// Update UI based on selection
281
updateSelectionUI(start, end);
282
}
283
};
284
285
const editor = new JSONEditor(container, options);
286
```
287
288
### Node Expansion Events
289
290
Handle node expansion and collapse events to track tree state changes.
291
292
```javascript { .api }
293
/**
294
* Expansion event callback in editor options
295
*/
296
interface ExpansionCallbacks {
297
onExpand?: (event: {
298
path: (string | number)[];
299
isExpand: boolean;
300
recursive: boolean;
301
}) => void;
302
}
303
```
304
305
**Usage Example:**
306
307
```javascript
308
const options = {
309
mode: "tree",
310
onExpand: ({ path, isExpand, recursive }) => {
311
const pathStr = path.join('.');
312
const action = isExpand ? "expanded" : "collapsed";
313
const scope = recursive ? " (recursive)" : "";
314
315
console.log(`Node ${pathStr} ${action}${scope}`);
316
317
// Save expansion state
318
saveExpansionState(path, isExpand);
319
}
320
};
321
```
322
323
## Advanced Tree Operations
324
325
### Navigate to Node
326
327
Navigate to and reveal a specific node in the tree by expanding its path.
328
329
```javascript
330
function navigateToNode(editor, targetPath) {
331
// Expand all parent nodes to make target visible
332
for (let i = 1; i < targetPath.length; i++) {
333
const parentPath = targetPath.slice(0, i);
334
editor.expand({
335
path: parentPath,
336
isExpand: true
337
});
338
}
339
340
// Select the target node
341
editor.setSelection(targetPath);
342
}
343
344
// Usage
345
navigateToNode(editor, ['config', 'database', 'host']);
346
```
347
348
### Batch Node Operations
349
350
Perform operations on multiple selected nodes.
351
352
```javascript
353
function processSelectedNodes(editor, processor) {
354
const selection = editor.getSelection();
355
356
if (selection.start && selection.end) {
357
const nodes = editor.getNodesByRange(
358
selection.start.path,
359
selection.end.path
360
);
361
362
const currentData = editor.get();
363
let modified = false;
364
365
nodes.forEach(node => {
366
const result = processor(node.value, node.path);
367
if (result !== node.value) {
368
// Update the data
369
setValueAtPath(currentData, node.path, result);
370
modified = true;
371
}
372
});
373
374
if (modified) {
375
editor.set(currentData);
376
}
377
}
378
}
379
380
// Usage: Convert all selected strings to uppercase
381
processSelectedNodes(editor, (value, path) => {
382
return typeof value === 'string' ? value.toUpperCase() : value;
383
});
384
```
385
386
### Tree State Management
387
388
Save and restore tree expansion and selection state.
389
390
```javascript
391
function saveTreeState(editor) {
392
return {
393
selection: editor.getSelection(),
394
// Note: Expansion state requires walking the tree
395
// This is a simplified example
396
mode: editor.getMode()
397
};
398
}
399
400
function restoreTreeState(editor, state) {
401
if (state.selection && state.selection.start) {
402
editor.setSelection(state.selection.start.path, state.selection.end?.path);
403
}
404
405
if (state.mode && state.mode !== editor.getMode()) {
406
editor.setMode(state.mode);
407
}
408
}
409
410
// Usage
411
const state = saveTreeState(editor);
412
// ... make changes ...
413
restoreTreeState(editor, state);
414
```
415
416
## Tree Configuration Options
417
418
### Visual Behavior
419
420
```javascript
421
const treeOptions = {
422
mode: "tree",
423
424
// Limit visible children before "show more" appears
425
maxVisibleChilds: 100,
426
427
// Restrict dragging to same parent
428
limitDragging: true,
429
430
// Sort object keys alphabetically
431
sortObjectKeys: false,
432
433
// Enable search functionality
434
search: true,
435
436
// Enable undo/redo
437
history: true
438
};
439
```
440
441
### Node Customization
442
443
```javascript
444
const customTreeOptions = {
445
mode: "tree",
446
447
// Customize node appearance
448
onClassName: ({ path, field, value }) => {
449
if (field === 'id') return 'id-field';
450
if (typeof value === 'number' && value < 0) return 'negative';
451
if (path.includes('deprecated')) return 'deprecated';
452
},
453
454
// Customize object/array node names
455
onNodeName: ({ type, size, value }) => {
456
if (type === 'array' && value.length === 0) return '[empty]';
457
if (type === 'object' && size === 0) return '{empty}';
458
return type === 'array' ? `[${size}]` : `{${size}}`;
459
},
460
461
// Control editability
462
onEditable: ({ path, field, value }) => {
463
// Make 'id' fields read-only
464
if (field === 'id') return { field: false, value: false };
465
466
// Make system fields read-only
467
if (field.startsWith('_')) return false;
468
469
return true; // Allow editing
470
}
471
};
472
```
473
474
## Tree Mode Limitations
475
476
- **Data Size**: Large datasets may impact performance; consider using preview mode for very large JSON
477
- **Deep Nesting**: Extremely deep object hierarchies may affect rendering performance
478
- **Memory Usage**: Full tree rendering keeps all nodes in memory
479
- **Browser Limits**: Very wide objects (many properties) may affect horizontal scrolling