or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

commands.mdconfiguration.mdcontent-operations.mdeditor-management.mdimage-upload.mdindex.mdmenus.mdselection.md

menus.mddocs/

0

# Menu System

1

2

The menu system provides programmatic access to editor toolbar menus for state management and custom interactions.

3

4

## Capabilities

5

6

### Change Menu State

7

8

Update the active state of toolbar menu items based on current selection.

9

10

```javascript { .api }

11

/**

12

* Update active state of all menu items

13

* Called automatically when selection changes, but can be called manually

14

*/

15

changeActive(): void;

16

```

17

18

**Usage Examples:**

19

20

```javascript

21

// Manually update menu states

22

editor.menus.changeActive();

23

24

// Update menu states after programmatic changes

25

editor.cmd.do('bold');

26

editor.menus.changeActive(); // Update bold button state

27

28

// Update states in custom event handlers

29

editor.customConfig.onchange = function(html) {

30

// Update menu states after content changes

31

setTimeout(() => {

32

editor.menus.changeActive();

33

}, 100);

34

};

35

```

36

37

### Access Individual Menus

38

39

Get access to individual menu instances for custom interactions.

40

41

```javascript { .api }

42

interface MenusAPI {

43

/** Individual menu instances, keyed by menu name */

44

menus: {[menuName: string]: MenuInstance};

45

46

/** Update active state of all menus */

47

changeActive(): void;

48

}

49

50

interface MenuInstance {

51

/** Menu type: 'click', 'droplist', or 'panel' */

52

type: string;

53

54

/** Menu DOM element */

55

$elem: Element;

56

57

/** Try to change active state (if supported) */

58

tryChangeActive?(): void;

59

60

/** Click handler (for click and panel types) */

61

onClick?(event: Event): void;

62

63

/** Dropdown list (for droplist type) */

64

droplist?: DroplistInstance;

65

66

/** Panel instance (for panel type) */

67

panel?: PanelInstance;

68

}

69

```

70

71

**Usage Examples:**

72

73

```javascript

74

// Access specific menu instance

75

const boldMenu = editor.menus.menus.bold;

76

if (boldMenu) {

77

console.log('Bold menu type:', boldMenu.type);

78

console.log('Bold menu element:', boldMenu.$elem);

79

}

80

81

// Check if menu exists

82

if (editor.menus.menus.italic) {

83

console.log('Italic menu is available');

84

}

85

86

// Get all available menus

87

const availableMenus = Object.keys(editor.menus.menus);

88

console.log('Available menus:', availableMenus);

89

90

// Programmatically trigger menu action

91

const linkMenu = editor.menus.menus.link;

92

if (linkMenu && linkMenu.onClick) {

93

// Save selection first

94

editor.selection.saveRange();

95

// Trigger link menu

96

linkMenu.onClick(new Event('click'));

97

}

98

```

99

100

## Available Menu Types

101

102

### Click Menus

103

104

Simple click-to-execute menus that perform immediate actions.

105

106

```javascript

107

// Examples of click menus:

108

// - bold, italic, underline, strikeThrough

109

// - undo, redo

110

// - justifyLeft, justifyCenter, justifyRight

111

112

const clickMenus = ['bold', 'italic', 'underline', 'strikeThrough', 'undo', 'redo'];

113

clickMenus.forEach(menuName => {

114

const menu = editor.menus.menus[menuName];

115

if (menu && menu.type === 'click') {

116

console.log(`${menuName} is a click menu`);

117

}

118

});

119

```

120

121

### Droplist Menus

122

123

Menus that show dropdown lists on hover.

124

125

```javascript

126

// Examples of droplist menus:

127

// - head (heading styles)

128

// - fontSize, fontName

129

// - foreColor, backColor

130

// - list (ordered/unordered)

131

132

const droplistMenus = ['head', 'fontSize', 'fontName', 'foreColor', 'backColor', 'list'];

133

droplistMenus.forEach(menuName => {

134

const menu = editor.menus.menus[menuName];

135

if (menu && menu.type === 'droplist' && menu.droplist) {

136

console.log(`${menuName} has a droplist`);

137

138

// Access droplist methods

139

// menu.droplist.show() - show droplist

140

// menu.droplist.hide() - hide droplist

141

}

142

});

143

```

144

145

### Panel Menus

146

147

Menus that open modal panels for complex interactions.

148

149

```javascript

150

// Examples of panel menus:

151

// - link (create/edit links)

152

// - image (insert images)

153

// - video (embed videos)

154

// - table (create tables)

155

// - code (code blocks)

156

// - emoticon (insert emojis)

157

158

const panelMenus = ['link', 'image', 'video', 'table', 'code', 'emoticon'];

159

panelMenus.forEach(menuName => {

160

const menu = editor.menus.menus[menuName];

161

if (menu && menu.type === 'panel' && menu.panel) {

162

console.log(`${menuName} has a panel`);

163

164

// Access panel methods

165

// menu.panel.show() - show panel

166

// menu.panel.hide() - hide panel

167

}

168

});

169

```

170

171

## Menu State Management

172

173

### Custom State Updates

174

175

```javascript

176

// Custom function to update specific menu states

177

function updateMenuStates() {

178

const menus = editor.menus.menus;

179

180

// Update bold menu state

181

if (menus.bold && menus.bold.tryChangeActive) {

182

menus.bold.tryChangeActive();

183

}

184

185

// Update italic menu state

186

if (menus.italic && menus.italic.tryChangeActive) {

187

menus.italic.tryChangeActive();

188

}

189

190

// Update all menu states

191

editor.menus.changeActive();

192

}

193

194

// Call after programmatic formatting

195

editor.cmd.do('bold');

196

updateMenuStates();

197

```

198

199

### Menu State Monitoring

200

201

```javascript

202

// Monitor menu state changes

203

function monitorMenuState(menuName) {

204

const menu = editor.menus.menus[menuName];

205

if (!menu || !menu.$elem) return;

206

207

// Check if menu is active

208

const isActive = menu.$elem.hasClass('w-e-active');

209

console.log(`${menuName} is ${isActive ? 'active' : 'inactive'}`);

210

211

return isActive;

212

}

213

214

// Usage

215

const isBold = monitorMenuState('bold');

216

const isItalic = monitorMenuState('italic');

217

218

// Monitor multiple menu states

219

function getActiveMenus() {

220

const activeMenus = [];

221

const menus = editor.menus.menus;

222

223

Object.keys(menus).forEach(menuName => {

224

if (monitorMenuState(menuName)) {

225

activeMenus.push(menuName);

226

}

227

});

228

229

return activeMenus;

230

}

231

232

const currentlyActive = getActiveMenus();

233

console.log('Currently active menus:', currentlyActive);

234

```

235

236

## Advanced Menu Interactions

237

238

### Custom Menu Event Handlers

239

240

```javascript

241

// Add custom behavior to existing menus

242

function enhanceMenus() {

243

const menus = editor.menus.menus;

244

245

// Enhance bold menu

246

if (menus.bold && menus.bold.$elem) {

247

menus.bold.$elem.on('click', function() {

248

console.log('Bold menu clicked');

249

// Custom analytics, validation, etc.

250

});

251

}

252

253

// Enhance image menu

254

if (menus.image && menus.image.$elem) {

255

menus.image.$elem.on('click', function() {

256

console.log('Image menu clicked');

257

// Custom image handling logic

258

});

259

}

260

}

261

262

// Call after editor creation

263

editor.create();

264

enhanceMenus();

265

```

266

267

### Menu Availability Checking

268

269

```javascript

270

// Check which menus are available

271

function checkMenuAvailability() {

272

const requiredMenus = ['bold', 'italic', 'link', 'image'];

273

const availableMenus = Object.keys(editor.menus.menus);

274

275

const missing = requiredMenus.filter(menu => !availableMenus.includes(menu));

276

277

if (missing.length > 0) {

278

console.warn('Missing required menus:', missing);

279

return false;

280

}

281

282

console.log('All required menus are available');

283

return true;

284

}

285

286

// Validate menu configuration

287

if (checkMenuAvailability()) {

288

// Proceed with menu-dependent functionality

289

console.log('Editor is properly configured');

290

} else {

291

// Handle missing menus

292

console.log('Some menus are missing from configuration');

293

}

294

```

295

296

### Menu Synchronization

297

298

```javascript

299

// Synchronize menu states with external UI

300

function syncWithExternalUI() {

301

// Get current menu states

302

const menuStates = {

303

bold: monitorMenuState('bold'),

304

italic: monitorMenuState('italic'),

305

underline: monitorMenuState('underline')

306

};

307

308

// Update external UI elements

309

Object.keys(menuStates).forEach(menuName => {

310

const externalButton = document.getElementById(`external-${menuName}`);

311

if (externalButton) {

312

externalButton.classList.toggle('active', menuStates[menuName]);

313

}

314

});

315

}

316

317

// Sync on selection change

318

editor.customConfig.onchange = function() {

319

setTimeout(syncWithExternalUI, 150);

320

};

321

322

// Manual sync

323

function manualSync() {

324

editor.menus.changeActive();

325

setTimeout(syncWithExternalUI, 100);

326

}

327

```

328

329

## Complete Menus API Interface

330

331

```javascript { .api }

332

interface MenusAPI {

333

/** Collection of individual menu instances */

334

menus: {[menuName: string]: MenuInstance};

335

336

/** Update active state of all menu items */

337

changeActive(): void;

338

}

339

340

interface MenuInstance {

341

/** Menu interaction type */

342

type: 'click' | 'droplist' | 'panel';

343

344

/** Menu DOM element */

345

$elem: Element;

346

347

/** Update active state if supported */

348

tryChangeActive?(): void;

349

350

/** Click event handler */

351

onClick?(event: Event): void;

352

353

/** Dropdown list for droplist menus */

354

droplist?: {

355

show(): void;

356

hide(): void;

357

showTimeoutId?: number;

358

hideTimeoutId?: number;

359

};

360

361

/** Panel for panel menus */

362

panel?: {

363

show(): void;

364

hide(): void;

365

};

366

}

367

```

368

369

## Menu Configuration Integration

370

371

The menu system works closely with the configuration system. See [Configuration](./configuration.md) for menu setup:

372

373

```javascript

374

// Configure available menus

375

editor.customConfig.menus = [

376

'head', 'bold', 'fontSize', 'fontName', 'italic', 'underline',

377

'strikeThrough', 'foreColor', 'backColor', 'link', 'list',

378

'justify', 'quote', 'emoticon', 'image', 'table', 'video',

379

'code', 'undo', 'redo'

380

];

381

382

// Create editor

383

editor.create();

384

385

// Access configured menus

386

const configuredMenus = Object.keys(editor.menus.menus);

387

console.log('Configured menus:', configuredMenus);

388

```