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
```