or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

checkbox.mdconfiguration.mdcontextmenu.mdcore.mddnd.mdevents.mdindex.mdplugins.mdsearch.md
tile.json

plugins.mddocs/

0

# Additional Plugins

1

2

State management, node types, sorting, context menus, and other specialized functionality. These plugins extend jsTree's core capabilities with additional features for enhanced tree management and user interaction.

3

4

## Capabilities

5

6

### State Plugin

7

8

Persistent state management for preserving tree state across sessions.

9

10

```javascript { .api }

11

/**

12

* State plugin configuration

13

*/

14

interface StateConfig {

15

/** Storage key for state data (default: "jstree") */

16

key?: string;

17

/** Events that trigger state save (default: ["changed.jstree", "open_node.jstree", "close_node.jstree"]) */

18

events?: Array<string>;

19

/** Time to live for state data in seconds (default: 3600) */

20

ttl?: number;

21

/** Custom filter function to determine what to save */

22

filter?: function;

23

/** Preserve loaded state on refresh (default: false) */

24

preserve_loaded?: boolean;

25

}

26

27

/**

28

* Save current tree state to storage

29

*/

30

save_state(): void;

31

32

/**

33

* Restore tree state from storage

34

*/

35

restore_state(): void;

36

37

/**

38

* Get current tree state object

39

* @returns State object containing selected nodes, opened nodes, etc.

40

*/

41

get_state(): object;

42

43

/**

44

* Set tree state from object

45

* @param state - State object to restore

46

* @param callback - Function to call when state is restored

47

*/

48

set_state(state: object, callback?: function): void;

49

50

/**

51

* Clear saved state from storage

52

*/

53

clear_state(): void;

54

```

55

56

**Usage Examples:**

57

58

```javascript

59

// Initialize with state plugin

60

$("#tree").jstree({

61

"plugins": ["state"],

62

"state": {

63

"key": "my-tree-state",

64

"events": ["changed.jstree", "open_node.jstree", "close_node.jstree"],

65

"ttl": 7200, // 2 hours

66

"filter": function(state) {

67

// Only save certain parts of state

68

return {

69

core: {

70

selected: state.core.selected,

71

open: state.core.open

72

}

73

};

74

}

75

}

76

});

77

78

// Manual state operations

79

const tree = $("#tree").jstree(true);

80

81

// Save current state

82

tree.save_state();

83

84

// Get state object

85

const currentState = tree.get_state();

86

console.log("Current state:", currentState);

87

88

// Restore specific state

89

tree.set_state({

90

core: {

91

selected: ["node_1", "node_2"],

92

open: ["parent_1", "parent_2"]

93

}

94

});

95

96

// Clear saved state

97

tree.clear_state();

98

```

99

100

### Types Plugin

101

102

Node type system with type-specific icons, behavior, and validation.

103

104

```javascript { .api }

105

/**

106

* Types plugin configuration

107

*/

108

interface TypesConfig {

109

/** Default node type (default: "default") */

110

default?: string;

111

/** Type definitions */

112

types?: {[type: string]: TypeDefinition};

113

}

114

115

interface TypeDefinition {

116

/** Maximum number of children (default: -1 for unlimited) */

117

max_children?: number;

118

/** Maximum depth for this type (default: -1 for unlimited) */

119

max_depth?: number;

120

/** Valid children types (default: -1 for all types) */

121

valid_children?: Array<string>|number;

122

/** Icon class or URL for this type */

123

icon?: string|boolean;

124

/** Additional node attributes */

125

li_attr?: object;

126

/** Additional anchor attributes */

127

a_attr?: object;

128

}

129

130

/**

131

* Get node type

132

* @param obj - Node to get type for

133

* @returns Node type string

134

*/

135

get_type(obj: string|object): string;

136

137

/**

138

* Set node type

139

* @param obj - Node to set type for

140

* @param type - New type name

141

* @returns True on success

142

*/

143

set_type(obj: string|object, type: string): boolean;

144

```

145

146

**Usage Examples:**

147

148

```javascript

149

// Initialize with types

150

$("#tree").jstree({

151

"plugins": ["types"],

152

"types": {

153

"default": {

154

"icon": "fa fa-file"

155

},

156

"folder": {

157

"icon": "fa fa-folder",

158

"valid_children": ["folder", "file"],

159

"max_children": 50

160

},

161

"file": {

162

"icon": "fa fa-file-o",

163

"valid_children": [],

164

"max_children": 0

165

},

166

"image": {

167

"icon": "fa fa-image",

168

"valid_children": [],

169

"li_attr": {"class": "image-node"}

170

}

171

},

172

"core": {

173

"data": [

174

{"text": "Documents", "type": "folder", "children": [

175

{"text": "report.pdf", "type": "file"},

176

{"text": "photo.jpg", "type": "image"}

177

]}

178

]

179

}

180

});

181

182

// Type operations

183

const tree = $("#tree").jstree(true);

184

185

// Get node type

186

const nodeType = tree.get_type("node_1");

187

console.log("Node type:", nodeType);

188

189

// Set node type

190

tree.set_type("node_1", "folder");

191

192

// Create typed nodes

193

tree.create_node("#", {

194

"text": "New Folder",

195

"type": "folder"

196

});

197

```

198

199

### Sort Plugin

200

201

Automatic and manual sorting of tree nodes.

202

203

```javascript { .api }

204

/**

205

* Sort plugin configuration

206

*/

207

interface SortConfig {

208

/** Custom sort function */

209

sort?: function;

210

/** Case sensitive sorting (default: false) */

211

case_sensitive?: boolean;

212

/** Natural sorting (handles numbers correctly) */

213

natural?: boolean;

214

}

215

216

/**

217

* Sort nodes alphabetically

218

* @param obj - Node to sort children of (default: root)

219

* @param deep - Also sort all descendants (default: false)

220

*/

221

sort(obj?: string|object, deep?: boolean): void;

222

```

223

224

**Usage Examples:**

225

226

```javascript

227

// Initialize with sorting

228

$("#tree").jstree({

229

"plugins": ["sort"],

230

"sort": {

231

"case_sensitive": false,

232

"natural": true,

233

"sort": function(a, b) {

234

// Custom sort logic

235

const nodeA = this.get_node(a);

236

const nodeB = this.get_node(b);

237

238

// Sort folders before files

239

if (nodeA.type === "folder" && nodeB.type !== "folder") return -1;

240

if (nodeA.type !== "folder" && nodeB.type === "folder") return 1;

241

242

// Then sort alphabetically

243

return nodeA.text.toLowerCase().localeCompare(nodeB.text.toLowerCase());

244

}

245

}

246

});

247

248

// Manual sorting

249

const tree = $("#tree").jstree(true);

250

tree.sort(); // Sort root level

251

tree.sort("folder_1", true); // Sort folder and all descendants

252

```

253

254

### Context Menu Plugin

255

256

Customizable right-click context menus with conditional items.

257

258

```javascript { .api }

259

/**

260

* Context menu plugin configuration

261

*/

262

interface ContextMenuConfig {

263

/** Select node when showing context menu (default: true) */

264

select_node?: boolean;

265

/** Show menu at node position vs cursor position (default: true) */

266

show_at_node?: boolean;

267

/** Menu items configuration */

268

items?: object|function;

269

}

270

271

interface ContextMenuItem {

272

/** Display label */

273

label?: string;

274

/** Icon class */

275

icon?: string;

276

/** Action function */

277

action?: function;

278

/** Submenu items */

279

submenu?: {[key: string]: ContextMenuItem};

280

/** Separator */

281

separator_before?: boolean;

282

separator_after?: boolean;

283

/** Conditional visibility */

284

visible?: boolean|function;

285

/** Conditional enablement */

286

disabled?: boolean|function;

287

/** Custom class name */

288

_class?: string;

289

}

290

291

/**

292

* Show context menu programmatically

293

* @param obj - Node to show menu for

294

* @param x - X coordinate (optional)

295

* @param y - Y coordinate (optional)

296

* @param e - Original event (optional)

297

*/

298

show_contextmenu(obj: string|object, x?: number, y?: number, e?: Event): void;

299

```

300

301

**Usage Examples:**

302

303

```javascript

304

// Initialize with context menu

305

$("#tree").jstree({

306

"plugins": ["contextmenu"],

307

"contextmenu": {

308

"items": function(node) {

309

return {

310

"create": {

311

"label": "Create",

312

"icon": "fa fa-plus",

313

"action": function(data) {

314

const inst = $.jstree.reference(data.reference);

315

const obj = inst.get_node(data.reference);

316

inst.create_node(obj, {}, "last", function(new_node) {

317

setTimeout(function() { inst.edit(new_node); }, 0);

318

});

319

}

320

},

321

"rename": {

322

"label": "Rename",

323

"icon": "fa fa-edit",

324

"action": function(data) {

325

const inst = $.jstree.reference(data.reference);

326

const obj = inst.get_node(data.reference);

327

inst.edit(obj);

328

}

329

},

330

"delete": {

331

"label": "Delete",

332

"icon": "fa fa-trash",

333

"separator_before": true,

334

"action": function(data) {

335

const inst = $.jstree.reference(data.reference);

336

const obj = inst.get_node(data.reference);

337

if (inst.is_selected(obj)) {

338

inst.delete_node(inst.get_selected());

339

} else {

340

inst.delete_node(obj);

341

}

342

}

343

},

344

"properties": {

345

"label": "Properties",

346

"icon": "fa fa-info",

347

"separator_before": true,

348

"visible": function(key, opt) {

349

// Only show for certain node types

350

return node.type === "file";

351

},

352

"action": function(data) {

353

showNodeProperties(data.reference);

354

}

355

}

356

};

357

}

358

}

359

});

360

361

// Dynamic context menu

362

$("#tree").jstree({

363

"plugins": ["contextmenu", "types"],

364

"contextmenu": {

365

"items": function(node) {

366

const items = {};

367

368

// Add type-specific items

369

if (node.type === "folder") {

370

items.create_folder = {

371

"label": "New Folder",

372

"action": function(data) {

373

// Create folder logic

374

}

375

};

376

items.create_file = {

377

"label": "New File",

378

"action": function(data) {

379

// Create file logic

380

}

381

};

382

}

383

384

// Add common items

385

items.rename = {

386

"label": "Rename",

387

"action": function(data) {

388

const inst = $.jstree.reference(data.reference);

389

inst.edit(data.reference);

390

}

391

};

392

393

return items;

394

}

395

}

396

});

397

```

398

399

### Unique Plugin

400

401

Ensures unique node names within parent nodes.

402

403

```javascript { .api }

404

/**

405

* Unique plugin configuration

406

*/

407

interface UniqueConfig {

408

/** Case sensitive uniqueness check (default: false) */

409

case_sensitive?: boolean;

410

/** Trim whitespace when checking (default: true) */

411

trim_whitespace?: boolean;

412

/** Custom duplicate callback */

413

duplicate?: function;

414

}

415

```

416

417

**Usage Examples:**

418

419

```javascript

420

// Initialize with unique names

421

$("#tree").jstree({

422

"plugins": ["unique"],

423

"unique": {

424

"case_sensitive": false,

425

"duplicate": function(name, counter) {

426

// Custom naming for duplicates

427

return name + " (" + counter + ")";

428

}

429

}

430

});

431

432

// Automatic duplicate handling

433

const tree = $("#tree").jstree(true);

434

tree.create_node("#", {"text": "New Item"}); // Creates "New Item"

435

tree.create_node("#", {"text": "New Item"}); // Creates "New Item (2)"

436

tree.create_node("#", {"text": "new item"}); // Creates "new item (3)" if case_sensitive: false

437

```

438

439

### Wholerow Plugin

440

441

Extends clickable area to full row width for easier interaction.

442

443

```javascript { .api }

444

/**

445

* Wholerow plugin configuration

446

*/

447

interface WholerowConfig {

448

/** Enable wholerow selection */

449

wholerow?: boolean;

450

}

451

```

452

453

**Usage Examples:**

454

455

```javascript

456

// Initialize with wholerow

457

$("#tree").jstree({

458

"plugins": ["wholerow"],

459

"wholerow": {

460

"wholerow": true

461

}

462

});

463

464

// The entire row becomes clickable, not just the text/icon

465

```

466

467

### Changed Plugin

468

469

Tracks and reports changes to the tree structure.

470

471

```javascript { .api }

472

/**

473

* Get array of changed node IDs since last call

474

* @param callback - Function to call with changed nodes

475

* @returns Array of changed node IDs

476

*/

477

get_changed(callback?: function): Array<string>;

478

```

479

480

**Usage Examples:**

481

482

```javascript

483

// Initialize with changed tracking

484

$("#tree").jstree({

485

"plugins": ["changed"]

486

});

487

488

// Get changed nodes

489

const tree = $("#tree").jstree(true);

490

const changedNodes = tree.get_changed();

491

console.log("Changed nodes:", changedNodes);

492

493

// Listen for changes

494

$("#tree").on("changed.jstree", function(e, data) {

495

console.log("Tree changed:", data.changed);

496

});

497

```

498

499

### Conditionalselect Plugin

500

501

Allows conditional node selection via callback functions.

502

503

```javascript { .api }

504

/**

505

* Conditionalselect plugin configuration

506

*/

507

interface ConditionalselectConfig {

508

/** Function to determine if node can be selected */

509

conditionalselect?: function;

510

}

511

512

type ConditionalSelectFunction = (node: object, event: Event) => boolean;

513

```

514

515

**Usage Examples:**

516

517

```javascript

518

// Initialize with conditional selection

519

$("#tree").jstree({

520

"plugins": ["conditionalselect"],

521

"conditionalselect": {

522

"conditionalselect": function(node, event) {

523

// Only allow selection of leaf nodes

524

return this.is_leaf(node);

525

}

526

}

527

});

528

529

// More complex conditions

530

$("#tree").jstree({

531

"plugins": ["conditionalselect", "types"],

532

"conditionalselect": {

533

"conditionalselect": function(node, event) {

534

// Prevent selection based on node type and user permissions

535

if (node.type === "readonly") return false;

536

if (node.li_attr && node.li_attr["data-locked"] === "true") return false;

537

538

// Check user permissions

539

const userRole = getCurrentUserRole();

540

if (userRole === "viewer" && node.type === "admin") return false;

541

542

return true;

543

}

544

}

545

});

546

```

547

548

### Massload Plugin

549

550

Enables loading multiple nodes in a single request for performance optimization.

551

552

```javascript { .api }

553

/**

554

* Massload plugin configuration

555

*/

556

interface MassloadConfig {

557

/** URL for mass loading endpoint */

558

url?: string;

559

/** Request data configuration */

560

data?: function;

561

}

562

```

563

564

**Usage Examples:**

565

566

```javascript

567

// Initialize with mass loading

568

$("#tree").jstree({

569

"plugins": ["massload"],

570

"massload": {

571

"url": "/api/nodes/massload",

572

"data": function(nodes) {

573

return {

574

"ids": nodes.join(","),

575

"timestamp": Date.now()

576

};

577

}

578

}

579

});

580

581

// Server endpoint should return data for multiple nodes at once

582

// instead of making individual requests for each node

583

```

584

585

## Plugin Integration Patterns

586

587

### Multi-Plugin Usage

588

589

Common patterns for combining multiple plugins effectively.

590

591

```javascript { .api }

592

/**

593

* Comprehensive tree setup with multiple plugins

594

*/

595

interface ComprehensiveTreeConfig {

596

plugins: Array<string>;

597

core: CoreConfig;

598

checkbox?: CheckboxConfig;

599

contextmenu?: ContextMenuConfig;

600

dnd?: DnDConfig;

601

search?: SearchConfig;

602

state?: StateConfig;

603

types?: TypesConfig;

604

sort?: SortConfig;

605

unique?: UniqueConfig;

606

wholerow?: WholerowConfig;

607

conditionalselect?: ConditionalselectConfig;

608

}

609

```

610

611

**Usage Examples:**

612

613

```javascript

614

// Full-featured tree setup

615

$("#tree").jstree({

616

"plugins": [

617

"checkbox", "contextmenu", "dnd", "search",

618

"state", "types", "sort", "unique", "wholerow"

619

],

620

"core": {

621

"check_callback": true,

622

"themes": {"stripes": true}

623

},

624

"checkbox": {

625

"three_state": true,

626

"cascade": "up+down+undetermined"

627

},

628

"contextmenu": {

629

"items": contextMenuBuilder

630

},

631

"dnd": {

632

"check_while_dragging": true,

633

"drag_selection": true

634

},

635

"search": {

636

"fuzzy": true,

637

"show_only_matches": true

638

},

639

"state": {

640

"key": "full-tree-state"

641

},

642

"types": {

643

"folder": {"icon": "fa fa-folder"},

644

"file": {"icon": "fa fa-file"}

645

},

646

"sort": {

647

"case_sensitive": false

648

}

649

});

650

651

// Event coordination across plugins

652

$("#tree").on("ready.jstree", function() {

653

// Tree is fully initialized with all plugins

654

const tree = $(this).jstree(true);

655

656

// Restore state

657

tree.restore_state();

658

659

// Enable search UI

660

$("#search-input").on("keyup", function() {

661

tree.search($(this).val());

662

});

663

});

664

```

665

666

## Types

667

668

```javascript { .api }

669

// Plugin-enhanced node object

670

interface EnhancedTreeNode extends TreeNode {

671

// State plugin

672

state?: {

673

loaded?: boolean;

674

opened?: boolean;

675

selected?: boolean;

676

disabled?: boolean;

677

};

678

679

// Types plugin

680

type?: string;

681

682

// Checkbox plugin (when enabled)

683

state?: {

684

checked?: boolean;

685

undetermined?: boolean;

686

checkbox_disabled?: boolean;

687

};

688

689

// Plugin-specific data

690

data?: {

691

[key: string]: any;

692

};

693

}

694

695

// Combined plugin settings

696

interface PluginSettings {

697

[plugin: string]: any;

698

}

699

```