CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jsoneditor

A web-based tool to view, edit, format, and validate JSON with multiple editing modes including tree, code, text, and preview

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

tree-operations.mddocs/

Tree Operations

Interactive tree editing capabilities including node manipulation, selection management, expansion control, and visual operations for tree, view, and form modes.

Capabilities

Expand All Nodes

Expand all collapsible nodes in the tree to show the complete data structure.

/**
 * Expand all fields in the tree
 * Only applicable for tree, view, and form modes
 */
expandAll(): void;

Usage Example:

// Expand all nodes to show full structure
editor.expandAll();

Collapse All Nodes

Collapse all expanded nodes to show only the top-level structure.

/**
 * Collapse all fields in the tree
 * Only applicable for tree, view, and form modes
 */
collapseAll(): void;

Usage Example:

// Collapse all nodes for compact view
editor.collapseAll();

Expand Specific Node

Expand or collapse a specific node at a given path with optional recursion.

/**
 * Expand or collapse a specific JSON node
 * @param options - Expansion configuration
 */
expand(options: ExpandOptions): void;

interface ExpandOptions {
  /** Path to the node to expand/collapse */
  path: (string | number)[];
  
  /** True to expand, false to collapse */
  isExpand: boolean;
  
  /** Apply to child nodes recursively (optional) */
  recursive?: boolean;
  
  /** Also expand/collapse all nodes in the path (optional) */
  withPath?: boolean;
}

Usage Example:

// Expand a specific node
editor.expand({
  path: ['users', 0, 'address'],
  isExpand: true
});

// Collapse a node and all its children
editor.expand({
  path: ['data'],
  isExpand: false,
  recursive: true
});

// Expand a node and ensure its path is visible
editor.expand({
  path: ['config', 'database', 'settings'],
  isExpand: true,
  withPath: true
});

Set Node Selection

Set selection for a range of nodes in the tree, supporting both single and multi-node selection.

/**
 * Set selection for a range of nodes
 * @param start - Path to start node (optional)
 * @param end - Path to end node (optional)
 */
setSelection(start?: (string | number)[], end?: (string | number)[]): void;

Usage Example:

// Select a single node
editor.setSelection(['users', 0, 'name']);

// Select a range of nodes
editor.setSelection(['users', 0], ['users', 2]);

// Clear selection
editor.setSelection();

Get Current Selection

Retrieve the currently selected nodes in the tree.

/**
 * Get the current selected nodes
 * @returns Object with start and end selection points
 */
getSelection(): { start: SerializableNode; end: SerializableNode };

interface SerializableNode {
  /** Value of the selected node */
  value: any;
  
  /** Path to the selected node */
  path: (string | number)[];
}

Usage Example:

const selection = editor.getSelection();

if (selection.start) {
  console.log('Selection start:', selection.start.path);
  console.log('Start value:', selection.start.value);
}

if (selection.end && selection.end.path !== selection.start?.path) {
  console.log('Multi-node selection to:', selection.end.path);
}

Get Nodes by Range

Get all nodes within a specified range, useful for batch operations on selected content.

/**
 * Get a list of all nodes within a specified range
 * @param start - Path to the first node in range  
 * @param end - Path to the last node in range
 * @returns Array of all nodes in the range
 */
getNodesByRange(start: (string | number)[], end: (string | number)[]): SerializableNode[];

Search Tree Content

Search for text within all nodes in the tree and return matching results.

/**
 * Search for text in all nodes of the tree
 * @param text - Text to search for
 * @returns Array of search result objects with node information
 */
search(text: string): SearchResult[];

interface SearchResult {
  /** Path to the node containing the match */
  path: (string | number)[];
  
  /** Field name where the match was found */
  field: string;
  
  /** Value containing the match */
  value: any;
  
  /** Node object reference */
  node: any;
}

Usage Example:

// Search for text in all nodes
const results = editor.search("example");

results.forEach(result => {
  console.log(`Found "${result.field}" at path: ${result.path.join('.')}`);
  console.log(`Value: ${result.value}`);
});

// Search for partial matches
const partialResults = editor.search("mail"); // Finds "email", "mailbox", etc.

// Navigate to first search result
if (results.length > 0) {
  editor.setSelection(results[0].path);
  
  // Expand path to make result visible
  editor.expand({
    path: results[0].path,
    isExpand: true,
    withPath: true
  });
}

Usage Example:

// Get all nodes in a range
const nodes = editor.getNodesByRange(['users', 0], ['users', 5]);

nodes.forEach(node => {
  console.log(`Node at ${node.path.join('.')}: ${node.value}`);
});

// Process nodes in selection range
const selection = editor.getSelection();
if (selection.start && selection.end) {
  const selectedNodes = editor.getNodesByRange(
    selection.start.path, 
    selection.end.path
  );
  
  // Perform batch operation
  selectedNodes.forEach(node => {
    // Process each selected node
  });
}

Selection Change Events

Handle selection changes with event callbacks to respond to user interactions.

/**
 * Selection change callback in editor options
 */
interface SelectionCallbacks {
  onSelectionChange?: (start?: SerializableNode, end?: SerializableNode) => void;
}

Usage Example:

const options = {
  mode: "tree",
  onSelectionChange: (start, end) => {
    if (!start) {
      console.log("Selection cleared");
      return;
    }
    
    const pathStr = start.path.join('.');
    console.log(`Selected: ${pathStr} = ${JSON.stringify(start.value)}`);
    
    if (end && end.path !== start.path) {
      const endPathStr = end.path.join('.');
      console.log(`Multi-selection to: ${endPathStr}`);
    }
    
    // Update UI based on selection
    updateSelectionUI(start, end);
  }
};

const editor = new JSONEditor(container, options);

Node Expansion Events

Handle node expansion and collapse events to track tree state changes.

/**
 * Expansion event callback in editor options
 */
interface ExpansionCallbacks {
  onExpand?: (event: {
    path: (string | number)[];
    isExpand: boolean;
    recursive: boolean;
  }) => void;
}

Usage Example:

const options = {
  mode: "tree",
  onExpand: ({ path, isExpand, recursive }) => {
    const pathStr = path.join('.');
    const action = isExpand ? "expanded" : "collapsed";
    const scope = recursive ? " (recursive)" : "";
    
    console.log(`Node ${pathStr} ${action}${scope}`);
    
    // Save expansion state
    saveExpansionState(path, isExpand);
  }
};

Advanced Tree Operations

Navigate to Node

Navigate to and reveal a specific node in the tree by expanding its path.

function navigateToNode(editor, targetPath) {
  // Expand all parent nodes to make target visible
  for (let i = 1; i < targetPath.length; i++) {
    const parentPath = targetPath.slice(0, i);
    editor.expand({
      path: parentPath,
      isExpand: true
    });
  }
  
  // Select the target node
  editor.setSelection(targetPath);
}

// Usage
navigateToNode(editor, ['config', 'database', 'host']);

Batch Node Operations

Perform operations on multiple selected nodes.

function processSelectedNodes(editor, processor) {
  const selection = editor.getSelection();
  
  if (selection.start && selection.end) {
    const nodes = editor.getNodesByRange(
      selection.start.path, 
      selection.end.path
    );
    
    const currentData = editor.get();
    let modified = false;
    
    nodes.forEach(node => {
      const result = processor(node.value, node.path);
      if (result !== node.value) {
        // Update the data
        setValueAtPath(currentData, node.path, result);
        modified = true;
      }
    });
    
    if (modified) {
      editor.set(currentData);
    }
  }
}

// Usage: Convert all selected strings to uppercase
processSelectedNodes(editor, (value, path) => {
  return typeof value === 'string' ? value.toUpperCase() : value;
});

Tree State Management

Save and restore tree expansion and selection state.

function saveTreeState(editor) {
  return {
    selection: editor.getSelection(),
    // Note: Expansion state requires walking the tree
    // This is a simplified example
    mode: editor.getMode()
  };
}

function restoreTreeState(editor, state) {
  if (state.selection && state.selection.start) {
    editor.setSelection(state.selection.start.path, state.selection.end?.path);
  }
  
  if (state.mode && state.mode !== editor.getMode()) {
    editor.setMode(state.mode);
  }
}

// Usage
const state = saveTreeState(editor);
// ... make changes ...
restoreTreeState(editor, state);

Tree Configuration Options

Visual Behavior

const treeOptions = {
  mode: "tree",
  
  // Limit visible children before "show more" appears
  maxVisibleChilds: 100,
  
  // Restrict dragging to same parent
  limitDragging: true,
  
  // Sort object keys alphabetically
  sortObjectKeys: false,
  
  // Enable search functionality
  search: true,
  
  // Enable undo/redo
  history: true
};

Node Customization

const customTreeOptions = {
  mode: "tree",
  
  // Customize node appearance
  onClassName: ({ path, field, value }) => {
    if (field === 'id') return 'id-field';
    if (typeof value === 'number' && value < 0) return 'negative';
    if (path.includes('deprecated')) return 'deprecated';
  },
  
  // Customize object/array node names  
  onNodeName: ({ type, size, value }) => {
    if (type === 'array' && value.length === 0) return '[empty]';
    if (type === 'object' && size === 0) return '{empty}';
    return type === 'array' ? `[${size}]` : `{${size}}`;
  },
  
  // Control editability
  onEditable: ({ path, field, value }) => {
    // Make 'id' fields read-only
    if (field === 'id') return { field: false, value: false };
    
    // Make system fields read-only
    if (field.startsWith('_')) return false;
    
    return true; // Allow editing
  }
};

Tree Mode Limitations

  • Data Size: Large datasets may impact performance; consider using preview mode for very large JSON
  • Deep Nesting: Extremely deep object hierarchies may affect rendering performance
  • Memory Usage: Full tree rendering keeps all nodes in memory
  • Browser Limits: Very wide objects (many properties) may affect horizontal scrolling

docs

configuration.md

editor-core.md

index.md

mode-management.md

preview-mode.md

schema-validation.md

text-operations.md

transform-operations.md

tree-operations.md

tile.json