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

events.mddocs/

0

# Events and Callbacks

1

2

Comprehensive guide to jsTree's event system, including core events, plugin-specific events, and custom event handling. jsTree uses jQuery's event system to provide extensive hooks for tree interactions and state changes.

3

4

## Capabilities

5

6

### Core Events

7

8

Fundamental events triggered during tree lifecycle and operations.

9

10

```javascript { .api }

11

/**

12

* Tree lifecycle events

13

*/

14

15

// Initialization events

16

"init.jstree": InitEvent;

17

"loading.jstree": LoadingEvent;

18

"loaded.jstree": LoadedEvent;

19

"ready.jstree": ReadyEvent;

20

"destroy.jstree": DestroyEvent;

21

22

// Rendering events

23

"redraw.jstree": RedrawEvent;

24

"refresh.jstree": RefreshEvent;

25

26

interface InitEvent {

27

instance: jsTree;

28

}

29

30

interface LoadingEvent {

31

instance: jsTree;

32

}

33

34

interface LoadedEvent {

35

instance: jsTree;

36

}

37

38

interface ReadyEvent {

39

instance: jsTree;

40

}

41

42

interface DestroyEvent {

43

instance: jsTree;

44

}

45

46

interface RedrawEvent {

47

nodes: Array<string>;

48

instance: jsTree;

49

}

50

51

interface RefreshEvent {

52

instance: jsTree;

53

}

54

```

55

56

**Usage Examples:**

57

58

```javascript

59

// Listen for lifecycle events

60

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

61

console.log("Tree initialized");

62

});

63

64

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

65

console.log("Tree is ready for interaction");

66

// Safe to call tree methods here

67

const tree = data.instance;

68

tree.open_all();

69

});

70

71

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

72

console.log("Tree destroyed, cleaning up...");

73

// Cleanup code here

74

});

75

76

// Loading state management

77

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

78

$("#loading-indicator").show();

79

});

80

81

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

82

$("#loading-indicator").hide();

83

});

84

```

85

86

### Node Events

87

88

Events triggered by node-specific operations and state changes.

89

90

```javascript { .api }

91

/**

92

* Node operation events

93

*/

94

95

// Node state events

96

"open_node.jstree": NodeEvent;

97

"close_node.jstree": NodeEvent;

98

"select_node.jstree": SelectEvent;

99

"deselect_node.jstree": SelectEvent;

100

"changed.jstree": ChangedEvent;

101

102

// Node modification events

103

"create_node.jstree": CreateEvent;

104

"rename_node.jstree": RenameEvent;

105

"delete_node.jstree": DeleteEvent;

106

"move_node.jstree": MoveEvent;

107

"copy_node.jstree": CopyEvent;

108

109

// Node interaction events

110

"activate_node.jstree": ActivateEvent;

111

"hover_node.jstree": HoverEvent;

112

"dehover_node.jstree": HoverEvent;

113

114

interface NodeEvent {

115

node: object;

116

instance: jsTree;

117

}

118

119

interface SelectEvent {

120

node: object;

121

selected: Array<string>;

122

event: Event;

123

instance: jsTree;

124

}

125

126

interface ChangedEvent {

127

selected: Array<string>;

128

event: Event;

129

instance: jsTree;

130

}

131

132

interface CreateEvent {

133

node: object;

134

parent: string;

135

position: number;

136

instance: jsTree;

137

}

138

139

interface RenameEvent {

140

node: object;

141

text: string;

142

old: string;

143

instance: jsTree;

144

}

145

146

interface DeleteEvent {

147

node: object;

148

parent: string;

149

instance: jsTree;

150

}

151

152

interface MoveEvent {

153

node: object;

154

parent: string;

155

position: number;

156

old_parent: string;

157

old_position: number;

158

is_multi: boolean;

159

old_instance: jsTree;

160

new_instance: jsTree;

161

instance: jsTree;

162

}

163

164

interface CopyEvent {

165

node: object;

166

original: object;

167

parent: string;

168

position: number;

169

old_parent: string;

170

old_position: number;

171

is_multi: boolean;

172

old_instance: jsTree;

173

new_instance: jsTree;

174

instance: jsTree;

175

}

176

177

interface ActivateEvent {

178

node: object;

179

event: Event;

180

instance: jsTree;

181

}

182

183

interface HoverEvent {

184

node: object;

185

instance: jsTree;

186

}

187

```

188

189

**Usage Examples:**

190

191

```javascript

192

// Node selection events

193

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

194

console.log("Selected node:", data.node.text);

195

console.log("All selected:", data.selected);

196

197

// Update UI based on selection

198

updateSelectionInfo(data.selected);

199

});

200

201

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

202

console.log("Deselected node:", data.node.text);

203

204

if (data.selected.length === 0) {

205

clearSelectionInfo();

206

}

207

});

208

209

// Node modification events

210

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

211

console.log("Created node:", data.node.text, "in parent:", data.parent);

212

213

// Save new node to server

214

saveNodeToServer(data.node);

215

});

216

217

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

218

console.log("Renamed node from", data.old, "to", data.text);

219

220

// Update server

221

updateNodeOnServer(data.node.id, {text: data.text});

222

});

223

224

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

225

console.log("Deleted node:", data.node.text);

226

227

// Confirm with user and update server

228

if (confirm("Permanently delete this item?")) {

229

deleteNodeOnServer(data.node.id);

230

}

231

});

232

233

// Node movement events

234

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

235

console.log("Moved node:", {

236

node: data.node.text,

237

from: data.old_parent,

238

to: data.parent,

239

oldPos: data.old_position,

240

newPos: data.position

241

});

242

243

// Update server with new structure

244

updateNodeParent(data.node.id, data.parent, data.position);

245

});

246

247

// Node state events

248

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

249

console.log("Opened node:", data.node.text);

250

251

// Load additional data when node opens

252

if (data.node.children.length === 0) {

253

loadNodeChildren(data.node.id);

254

}

255

});

256

```

257

258

### Plugin Events

259

260

Events specific to individual plugins.

261

262

```javascript { .api }

263

/**

264

* Checkbox plugin events

265

*/

266

"check_node.jstree": CheckboxEvent;

267

"uncheck_node.jstree": CheckboxEvent;

268

269

interface CheckboxEvent {

270

node: object;

271

selected: Array<string>;

272

event: Event;

273

instance: jsTree;

274

}

275

276

/**

277

* Search plugin events

278

*/

279

"search.jstree": SearchEvent;

280

"clear_search.jstree": ClearSearchEvent;

281

282

interface SearchEvent {

283

nodes: Array<string>;

284

str: string;

285

res: Array<object>;

286

instance: jsTree;

287

}

288

289

interface ClearSearchEvent {

290

instance: jsTree;

291

}

292

293

/**

294

* DnD plugin events (using vakata namespace)

295

*/

296

"dnd_start.vakata": DnDEvent;

297

"dnd_move.vakata": DnDEvent;

298

"dnd_stop.vakata": DnDEvent;

299

300

interface DnDEvent {

301

element: jQuery;

302

target: jQuery;

303

helper: jQuery;

304

event?: Event;

305

}

306

307

/**

308

* State plugin events

309

*/

310

"state_ready.jstree": StateEvent;

311

312

interface StateEvent {

313

instance: jsTree;

314

}

315

```

316

317

**Usage Examples:**

318

319

```javascript

320

// Checkbox events

321

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

322

console.log("Checked:", data.node.text);

323

console.log("All checked nodes:", data.selected);

324

325

// Update summary

326

updateCheckedSummary(data.selected);

327

});

328

329

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

330

console.log("Unchecked:", data.node.text);

331

updateCheckedSummary(data.selected);

332

});

333

334

// Search events

335

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

336

console.log(`Found ${data.nodes.length} matches for "${data.str}"`);

337

$("#search-results").text(`${data.nodes.length} results`);

338

339

if (data.nodes.length === 0) {

340

$("#no-results").show();

341

} else {

342

$("#no-results").hide();

343

}

344

});

345

346

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

347

$("#search-results").text("");

348

$("#no-results").hide();

349

});

350

351

// DnD events

352

$(document).on("dnd_start.vakata", function(e, data) {

353

console.log("Drag started");

354

$("body").addClass("dragging");

355

});

356

357

$(document).on("dnd_stop.vakata", function(e, data) {

358

console.log("Drag stopped");

359

$("body").removeClass("dragging");

360

});

361

362

// State events

363

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

364

console.log("State restored");

365

// Tree state has been restored from storage

366

});

367

```

368

369

### Event Binding Patterns

370

371

Common patterns for binding and managing events.

372

373

```javascript { .api }

374

/**

375

* Event binding utilities and patterns

376

*/

377

interface EventBindingPatterns {

378

/** Bind multiple events at once */

379

bindMultiple: (events: object) => void;

380

/** Bind with context */

381

bindWithContext: (event: string, handler: function, context: object) => void;

382

/** One-time event binding */

383

bindOnce: (event: string, handler: function) => void;

384

/** Conditional event binding */

385

bindConditional: (event: string, condition: function, handler: function) => void;

386

}

387

```

388

389

**Usage Examples:**

390

391

```javascript

392

// Multiple event binding

393

$("#tree").on({

394

"select_node.jstree": function(e, data) {

395

handleNodeSelection(data);

396

},

397

"deselect_node.jstree": function(e, data) {

398

handleNodeDeselection(data);

399

},

400

"open_node.jstree": function(e, data) {

401

handleNodeOpen(data);

402

},

403

"close_node.jstree": function(e, data) {

404

handleNodeClose(data);

405

}

406

});

407

408

// Event delegation for dynamic trees

409

$(document).on("select_node.jstree", ".dynamic-tree", function(e, data) {

410

// Handle selection for any tree with class 'dynamic-tree'

411

console.log("Dynamic tree selection:", data.node.text);

412

});

413

414

// One-time event binding

415

$("#tree").one("ready.jstree", function(e, data) {

416

// This will only run once when tree is first ready

417

initializeTreeUI(data.instance);

418

});

419

420

// Conditional event handling

421

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

422

// Only handle if user has permission

423

if (hasDeletePermission(data.node)) {

424

confirmAndDelete(data.node);

425

} else {

426

e.preventDefault();

427

showPermissionError();

428

}

429

});

430

431

// Event namespacing for cleanup

432

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

433

handleSelection(data);

434

});

435

436

// Later, remove only this namespace

437

$("#tree").off(".myapp");

438

```

439

440

### Custom Events

441

442

Creating and triggering custom events within jsTree context.

443

444

```javascript { .api }

445

/**

446

* Custom event creation and triggering

447

*/

448

interface CustomEvents {

449

/** Trigger custom event */

450

trigger: (event: string, data?: object) => void;

451

/** Create custom event type */

452

createEventType: (name: string, handler: function) => void;

453

}

454

455

// Custom event data structure

456

interface CustomEventData {

457

custom: boolean;

458

data: any;

459

instance: jsTree;

460

[key: string]: any;

461

}

462

```

463

464

**Usage Examples:**

465

466

```javascript

467

// Define custom events

468

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

469

console.log("Custom validation triggered:", data);

470

471

// Perform custom validation logic

472

const isValid = validateNodeData(data.node);

473

474

if (!isValid) {

475

e.preventDefault();

476

showValidationError(data.node);

477

}

478

});

479

480

// Trigger custom events

481

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

482

tree.element.trigger("custom_validation.jstree", {

483

node: tree.get_node("some_node"),

484

validationType: "business_rules",

485

timestamp: Date.now()

486

});

487

488

// Custom event for business logic

489

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

490

// Log node operations for audit trail

491

auditLog.record({

492

action: data.action,

493

nodeId: data.node.id,

494

userId: getCurrentUser().id,

495

timestamp: new Date().toISOString()

496

});

497

});

498

499

// Usage in tree operations

500

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

501

// Trigger audit event

502

$(this).trigger("node_audit.jstree", {

503

action: "create",

504

node: data.node

505

});

506

});

507

```

508

509

### Event Performance and Optimization

510

511

Best practices for event handling performance.

512

513

```javascript { .api }

514

/**

515

* Performance optimization patterns

516

*/

517

interface EventPerformance {

518

/** Debounced event handling */

519

debounce: (handler: function, delay: number) => function;

520

/** Throttled event handling */

521

throttle: (handler: function, limit: number) => function;

522

/** Batch event processing */

523

batchProcess: (events: Array<object>) => void;

524

}

525

```

526

527

**Usage Examples:**

528

529

```javascript

530

// Debounced search

531

let searchTimeout;

532

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

533

clearTimeout(searchTimeout);

534

searchTimeout = setTimeout(function() {

535

updateSearchAnalytics(data.str, data.nodes.length);

536

}, 300);

537

});

538

539

// Throttled selection updates

540

let lastSelectionUpdate = 0;

541

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

542

const now = Date.now();

543

if (now - lastSelectionUpdate > 100) { // Throttle to 10fps

544

updateSelectionUI(data.selected);

545

lastSelectionUpdate = now;

546

}

547

});

548

549

// Batch processing for multiple operations

550

let pendingUpdates = [];

551

$("#tree").on("move_node.jstree copy_node.jstree delete_node.jstree", function(e, data) {

552

pendingUpdates.push({

553

event: e.type,

554

data: data,

555

timestamp: Date.now()

556

});

557

558

// Process in batches

559

if (pendingUpdates.length >= 10) {

560

processBatch(pendingUpdates);

561

pendingUpdates = [];

562

}

563

});

564

565

// Process remaining updates periodically

566

setInterval(function() {

567

if (pendingUpdates.length > 0) {

568

processBatch(pendingUpdates);

569

pendingUpdates = [];

570

}

571

}, 1000);

572

573

// Memory cleanup

574

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

575

// Clear timeouts and intervals

576

clearTimeout(searchTimeout);

577

clearInterval(batchProcessor);

578

579

// Remove global event listeners

580

$(document).off(".tree-app");

581

$(window).off(".tree-app");

582

});

583

```

584

585

### Error Events

586

587

Events for error handling and debugging.

588

589

```javascript { .api }

590

/**

591

* Error events and handling

592

*/

593

"error.jstree": ErrorEvent;

594

595

interface ErrorEvent {

596

error: string;

597

plugin: string;

598

id: string;

599

reason: string;

600

data: any;

601

instance: jsTree;

602

}

603

```

604

605

**Usage Examples:**

606

607

```javascript

608

// Global error handling

609

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

610

console.error("jsTree error:", {

611

error: data.error,

612

plugin: data.plugin,

613

reason: data.reason,

614

data: data.data

615

});

616

617

// Show user-friendly error message

618

showErrorNotification("An error occurred while updating the tree");

619

620

// Log to error tracking service

621

errorTracker.log("jstree_error", {

622

error: data.error,

623

plugin: data.plugin,

624

reason: data.reason,

625

url: window.location.href,

626

userAgent: navigator.userAgent

627

});

628

});

629

630

// Plugin-specific error handling

631

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

632

if (data.plugin === "search") {

633

$("#search-error").show().text("Search failed: " + data.reason);

634

} else if (data.plugin === "core" && data.error === "load_node") {

635

showRetryDialog("Failed to load tree data. Retry?", function() {

636

// Retry loading

637

data.instance.refresh();

638

});

639

}

640

});

641

```

642

643

## Types

644

645

```javascript { .api }

646

// Base event interface

647

interface TreeEvent {

648

type: string;

649

target: Element;

650

currentTarget: Element;

651

instance: jsTree;

652

timeStamp: number;

653

}

654

655

// Event data union type

656

type EventData =

657

| InitEvent

658

| NodeEvent

659

| SelectEvent

660

| CreateEvent

661

| RenameEvent

662

| DeleteEvent

663

| MoveEvent

664

| CopyEvent

665

| SearchEvent

666

| CheckboxEvent

667

| ErrorEvent;

668

669

// Event handler type

670

type EventHandler<T = EventData> = (event: jQuery.Event, data: T) => void;

671

672

// Event binding options

673

interface EventBindingOptions {

674

namespace?: string;

675

once?: boolean;

676

passive?: boolean;

677

capture?: boolean;

678

}

679

```