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

contextmenu.mddocs/

0

# Context Menu System

1

2

Customizable right-click context menus with support for custom items, submenus, and conditional visibility. The context menu plugin provides an intuitive way to access tree operations and custom actions through right-click interactions.

3

4

## Capabilities

5

6

### Context Menu Configuration

7

8

Configuration options for the context menu plugin behavior.

9

10

```javascript { .api }

11

/**

12

* Context menu plugin configuration

13

*/

14

interface ContextMenuConfig {

15

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

16

select_node?: boolean;

17

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

18

show_at_node?: boolean;

19

/** Menu items configuration */

20

items?: object|function;

21

}

22

23

interface ContextMenuItem {

24

/** Display label */

25

label?: string;

26

/** Icon class */

27

icon?: string;

28

/** Action function */

29

action?: function;

30

/** Submenu items */

31

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

32

/** Separator before item */

33

separator_before?: boolean;

34

/** Separator after item */

35

separator_after?: boolean;

36

/** Conditional visibility */

37

visible?: boolean|function;

38

/** Conditional enablement */

39

disabled?: boolean|function;

40

/** Custom CSS class name */

41

_class?: string;

42

/** Shortcut key display */

43

shortcut?: string;

44

/** Shortcut key combination */

45

shortcut_label?: string;

46

}

47

48

// Usage in tree initialization

49

const config = {

50

"plugins": ["contextmenu"],

51

"contextmenu": {

52

"select_node": true,

53

"show_at_node": true,

54

"items": contextMenuBuilder

55

}

56

};

57

```

58

59

**Usage Examples:**

60

61

```javascript

62

// Initialize tree with context menu

63

$("#tree").jstree({

64

"core": {

65

"data": ["Item 1", "Item 2", "Folder"],

66

"check_callback": true

67

},

68

"plugins": ["contextmenu"],

69

"contextmenu": {

70

"items": function(node) {

71

return {

72

"create": {

73

"label": "Create",

74

"action": function(data) {

75

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

76

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

77

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

78

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

79

});

80

}

81

}

82

};

83

}

84

}

85

});

86

87

// Get instance for context menu operations

88

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

89

```

90

91

### Context Menu Methods

92

93

Methods for programmatically controlling context menus.

94

95

```javascript { .api }

96

/**

97

* Show context menu programmatically

98

* @param obj - Node to show menu for

99

* @param x - X coordinate (optional)

100

* @param y - Y coordinate (optional)

101

* @param e - Original event (optional)

102

*/

103

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

104

```

105

106

**Usage Examples:**

107

108

```javascript

109

// Show context menu programmatically

110

tree.show_contextmenu("node_1");

111

112

// Show at specific coordinates

113

tree.show_contextmenu("node_1", 100, 200);

114

115

// Show context menu on custom trigger

116

$("#custom-button").click(function() {

117

const selectedNodes = tree.get_selected();

118

if (selectedNodes.length > 0) {

119

tree.show_contextmenu(selectedNodes[0]);

120

}

121

});

122

```

123

124

### Static Menu Items

125

126

Configuration for static menu items that don't change based on context.

127

128

```javascript { .api }

129

/**

130

* Static menu items configuration

131

*/

132

interface StaticMenuItems {

133

[key: string]: ContextMenuItem;

134

}

135

```

136

137

**Usage Examples:**

138

139

```javascript

140

// Static menu items

141

$("#tree").jstree({

142

"plugins": ["contextmenu"],

143

"contextmenu": {

144

"items": {

145

"create": {

146

"label": "Create",

147

"icon": "fa fa-plus",

148

"action": function(data) {

149

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

150

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

151

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

152

inst.edit(new_node);

153

});

154

}

155

},

156

"rename": {

157

"label": "Rename",

158

"icon": "fa fa-edit",

159

"shortcut": "F2",

160

"action": function(data) {

161

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

162

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

163

inst.edit(obj);

164

}

165

},

166

"delete": {

167

"label": "Delete",

168

"icon": "fa fa-trash",

169

"shortcut": "Del",

170

"separator_before": true,

171

"action": function(data) {

172

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

173

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

174

if (confirm("Delete " + obj.text + "?")) {

175

inst.delete_node(obj);

176

}

177

}

178

}

179

}

180

}

181

});

182

```

183

184

### Dynamic Menu Items

185

186

Configuration for menu items that change based on the selected node or context.

187

188

```javascript { .api }

189

/**

190

* Dynamic menu items function

191

* @param node - Node that was right-clicked

192

* @returns Menu items object

193

*/

194

type DynamicMenuFunction = (node: object) => {[key: string]: ContextMenuItem};

195

```

196

197

**Usage Examples:**

198

199

```javascript

200

// Dynamic menu based on node type

201

$("#tree").jstree({

202

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

203

"contextmenu": {

204

"items": function(node) {

205

const items = {};

206

207

// Common items for all nodes

208

items.rename = {

209

"label": "Rename",

210

"action": function(data) {

211

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

212

inst.edit(data.reference);

213

}

214

};

215

216

// Type-specific items

217

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

218

items.create_folder = {

219

"label": "New Folder",

220

"icon": "fa fa-folder",

221

"action": function(data) {

222

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

223

inst.create_node(data.reference, {

224

"text": "New Folder",

225

"type": "folder"

226

}, "last", function(new_node) {

227

inst.edit(new_node);

228

});

229

}

230

};

231

232

items.create_file = {

233

"label": "New File",

234

"icon": "fa fa-file",

235

"action": function(data) {

236

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

237

inst.create_node(data.reference, {

238

"text": "New File",

239

"type": "file"

240

}, "last", function(new_node) {

241

inst.edit(new_node);

242

});

243

}

244

};

245

}

246

247

// Permission-based items

248

if (hasDeletePermission(node)) {

249

items.delete = {

250

"label": "Delete",

251

"icon": "fa fa-trash",

252

"separator_before": true,

253

"action": function(data) {

254

if (confirm("Delete this item?")) {

255

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

256

inst.delete_node(data.reference);

257

}

258

}

259

};

260

}

261

262

return items;

263

}

264

}

265

});

266

```

267

268

### Submenus

269

270

Configuration for nested submenu items.

271

272

```javascript { .api }

273

/**

274

* Submenu configuration

275

*/

276

interface SubmenuConfig {

277

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

278

}

279

```

280

281

**Usage Examples:**

282

283

```javascript

284

// Context menu with submenus

285

$("#tree").jstree({

286

"plugins": ["contextmenu"],

287

"contextmenu": {

288

"items": {

289

"create": {

290

"label": "Create",

291

"icon": "fa fa-plus",

292

"submenu": {

293

"folder": {

294

"label": "Folder",

295

"icon": "fa fa-folder",

296

"action": function(data) {

297

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

298

inst.create_node(data.reference, {

299

"text": "New Folder",

300

"type": "folder"

301

});

302

}

303

},

304

"file": {

305

"label": "File",

306

"icon": "fa fa-file",

307

"action": function(data) {

308

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

309

inst.create_node(data.reference, {

310

"text": "New File",

311

"type": "file"

312

});

313

}

314

},

315

"separator": {

316

"separator_before": true

317

},

318

"template": {

319

"label": "From Template",

320

"icon": "fa fa-copy",

321

"submenu": {

322

"html": {

323

"label": "HTML File",

324

"action": function(data) {

325

createFromTemplate(data.reference, "html");

326

}

327

},

328

"css": {

329

"label": "CSS File",

330

"action": function(data) {

331

createFromTemplate(data.reference, "css");

332

}

333

}

334

}

335

}

336

}

337

},

338

"edit": {

339

"label": "Edit",

340

"submenu": {

341

"rename": {

342

"label": "Rename",

343

"action": function(data) {

344

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

345

inst.edit(data.reference);

346

}

347

},

348

"properties": {

349

"label": "Properties",

350

"action": function(data) {

351

showProperties(data.reference);

352

}

353

}

354

}

355

}

356

}

357

}

358

});

359

```

360

361

### Conditional Menu Items

362

363

Configuration for menu items with conditional visibility and enablement.

364

365

```javascript { .api }

366

/**

367

* Conditional visibility function

368

* @param key - Menu item key

369

* @param opt - Menu options

370

* @returns True if item should be visible

371

*/

372

type VisibilityFunction = (key: string, opt: object) => boolean;

373

374

/**

375

* Conditional enablement function

376

* @param key - Menu item key

377

* @param opt - Menu options

378

* @returns True if item should be enabled

379

*/

380

type DisabledFunction = (key: string, opt: object) => boolean;

381

```

382

383

**Usage Examples:**

384

385

```javascript

386

// Conditional menu items

387

$("#tree").jstree({

388

"plugins": ["contextmenu"],

389

"contextmenu": {

390

"items": function(node) {

391

return {

392

"cut": {

393

"label": "Cut",

394

"action": function(data) {

395

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

396

inst.cut(data.reference);

397

},

398

"visible": function(key, opt) {

399

// Only show if node is not root

400

return node.parent !== "#";

401

}

402

},

403

"copy": {

404

"label": "Copy",

405

"action": function(data) {

406

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

407

inst.copy(data.reference);

408

}

409

},

410

"paste": {

411

"label": "Paste",

412

"action": function(data) {

413

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

414

inst.paste(data.reference);

415

},

416

"visible": function(key, opt) {

417

const inst = $.jstree.reference(opt.$trigger);

418

return inst.can_paste();

419

},

420

"disabled": function(key, opt) {

421

const inst = $.jstree.reference(opt.$trigger);

422

return !inst.can_paste();

423

}

424

},

425

"delete": {

426

"label": "Delete",

427

"action": function(data) {

428

if (confirm("Delete this item?")) {

429

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

430

inst.delete_node(data.reference);

431

}

432

},

433

"visible": function(key, opt) {

434

// Only show if user has delete permission

435

return hasPermission("delete", node);

436

}

437

}

438

};

439

}

440

}

441

});

442

```

443

444

### Context Menu Events

445

446

Events triggered during context menu operations.

447

448

```javascript { .api }

449

// Context menu specific events

450

"show_contextmenu.jstree": ContextMenuEvent;

451

"hide_contextmenu.jstree": ContextMenuEvent;

452

453

interface ContextMenuEvent {

454

node: object;

455

x: number;

456

y: number;

457

instance: jsTree;

458

}

459

```

460

461

**Usage Examples:**

462

463

```javascript

464

// Listen for context menu events

465

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

466

console.log("Context menu shown for:", data.node.text);

467

console.log("Position:", data.x, data.y);

468

});

469

470

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

471

console.log("Context menu hidden");

472

});

473

474

// Custom context menu styling based on node

475

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

476

const menuContainer = $(".jstree-contextmenu");

477

478

// Add custom class based on node type

479

menuContainer.removeClass("folder-menu file-menu");

480

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

481

menuContainer.addClass("folder-menu");

482

} else if (data.node.type === "file") {

483

menuContainer.addClass("file-menu");

484

}

485

});

486

```

487

488

### Advanced Context Menu Patterns

489

490

Advanced configuration patterns for complex scenarios.

491

492

```javascript { .api }

493

/**

494

* Advanced context menu patterns

495

*/

496

interface AdvancedContextMenuConfig {

497

/** Multi-selection context menu */

498

multi_selection?: boolean;

499

/** Custom menu positioning */

500

position?: function;

501

/** Menu theme/styling */

502

theme?: string;

503

/** Animation settings */

504

animation?: object;

505

}

506

```

507

508

**Usage Examples:**

509

510

```javascript

511

// Multi-selection context menu

512

$("#tree").jstree({

513

"plugins": ["contextmenu"],

514

"contextmenu": {

515

"items": function(node) {

516

const inst = $.jstree.reference($("#tree"));

517

const selected = inst.get_selected();

518

const isMultiple = selected.length > 1;

519

520

const items = {};

521

522

if (isMultiple) {

523

items.multi_delete = {

524

"label": "Delete Selected (" + selected.length + ")",

525

"icon": "fa fa-trash",

526

"action": function(data) {

527

if (confirm("Delete " + selected.length + " items?")) {

528

inst.delete_node(selected);

529

}

530

}

531

};

532

533

items.multi_move = {

534

"label": "Move Selected",

535

"icon": "fa fa-arrows",

536

"action": function(data) {

537

// Show move dialog for multiple items

538

showMoveDialog(selected);

539

}

540

};

541

} else {

542

// Single item context menu

543

items.rename = {

544

"label": "Rename",

545

"action": function(data) {

546

inst.edit(data.reference);

547

}

548

};

549

}

550

551

return items;

552

}

553

}

554

});

555

556

// Integration with other plugins

557

$("#tree").jstree({

558

"plugins": ["contextmenu", "dnd", "clipboard"],

559

"contextmenu": {

560

"items": function(node) {

561

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

562

563

return {

564

"cut": {

565

"label": "Cut",

566

"action": function(data) {

567

tree.cut(data.reference);

568

}

569

},

570

"copy": {

571

"label": "Copy",

572

"action": function(data) {

573

tree.copy(data.reference);

574

}

575

},

576

"paste": {

577

"label": "Paste",

578

"action": function(data) {

579

tree.paste(data.reference);

580

},

581

"visible": function() {

582

return tree.can_paste();

583

}

584

}

585

};

586

}

587

}

588

});

589

```

590

591

## Types

592

593

```javascript { .api }

594

// Context menu data structures

595

interface ContextMenuData {

596

reference: jQuery;

597

element: jQuery;

598

position: {x: number, y: number};

599

node: object;

600

}

601

602

// Menu action function signature

603

type MenuActionFunction = (data: ContextMenuData) => void;

604

605

// Context menu settings

606

interface ContextMenuSettings {

607

select_node: boolean;

608

show_at_node: boolean;

609

items: object|DynamicMenuFunction;

610

}

611

```