CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wangeditor

Lightweight web-based rich text editor (WYSIWYG editor) built with JavaScript and CSS for modern browsers

Pending
Overview
Eval results
Files

menus.mddocs/

Menu System

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

Capabilities

Change Menu State

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

/**
 * Update active state of all menu items
 * Called automatically when selection changes, but can be called manually
 */
changeActive(): void;

Usage Examples:

// Manually update menu states
editor.menus.changeActive();

// Update menu states after programmatic changes
editor.cmd.do('bold');
editor.menus.changeActive(); // Update bold button state

// Update states in custom event handlers
editor.customConfig.onchange = function(html) {
    // Update menu states after content changes
    setTimeout(() => {
        editor.menus.changeActive();
    }, 100);
};

Access Individual Menus

Get access to individual menu instances for custom interactions.

interface MenusAPI {
  /** Individual menu instances, keyed by menu name */
  menus: {[menuName: string]: MenuInstance};
  
  /** Update active state of all menus */
  changeActive(): void;
}

interface MenuInstance {
  /** Menu type: 'click', 'droplist', or 'panel' */
  type: string;
  
  /** Menu DOM element */
  $elem: Element;
  
  /** Try to change active state (if supported) */
  tryChangeActive?(): void;
  
  /** Click handler (for click and panel types) */
  onClick?(event: Event): void;
  
  /** Dropdown list (for droplist type) */
  droplist?: DroplistInstance;
  
  /** Panel instance (for panel type) */
  panel?: PanelInstance;
}

Usage Examples:

// Access specific menu instance
const boldMenu = editor.menus.menus.bold;
if (boldMenu) {
    console.log('Bold menu type:', boldMenu.type);
    console.log('Bold menu element:', boldMenu.$elem);
}

// Check if menu exists
if (editor.menus.menus.italic) {
    console.log('Italic menu is available');
}

// Get all available menus
const availableMenus = Object.keys(editor.menus.menus);
console.log('Available menus:', availableMenus);

// Programmatically trigger menu action
const linkMenu = editor.menus.menus.link;
if (linkMenu && linkMenu.onClick) {
    // Save selection first
    editor.selection.saveRange();
    // Trigger link menu
    linkMenu.onClick(new Event('click'));
}

Available Menu Types

Click Menus

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

// Examples of click menus:
// - bold, italic, underline, strikeThrough
// - undo, redo
// - justifyLeft, justifyCenter, justifyRight

const clickMenus = ['bold', 'italic', 'underline', 'strikeThrough', 'undo', 'redo'];
clickMenus.forEach(menuName => {
    const menu = editor.menus.menus[menuName];
    if (menu && menu.type === 'click') {
        console.log(`${menuName} is a click menu`);
    }
});

Droplist Menus

Menus that show dropdown lists on hover.

// Examples of droplist menus:
// - head (heading styles)
// - fontSize, fontName
// - foreColor, backColor
// - list (ordered/unordered)

const droplistMenus = ['head', 'fontSize', 'fontName', 'foreColor', 'backColor', 'list'];
droplistMenus.forEach(menuName => {
    const menu = editor.menus.menus[menuName];
    if (menu && menu.type === 'droplist' && menu.droplist) {
        console.log(`${menuName} has a droplist`);
        
        // Access droplist methods
        // menu.droplist.show() - show droplist
        // menu.droplist.hide() - hide droplist
    }
});

Panel Menus

Menus that open modal panels for complex interactions.

// Examples of panel menus:
// - link (create/edit links)
// - image (insert images)
// - video (embed videos)
// - table (create tables)
// - code (code blocks)
// - emoticon (insert emojis)

const panelMenus = ['link', 'image', 'video', 'table', 'code', 'emoticon'];
panelMenus.forEach(menuName => {
    const menu = editor.menus.menus[menuName];
    if (menu && menu.type === 'panel' && menu.panel) {
        console.log(`${menuName} has a panel`);
        
        // Access panel methods
        // menu.panel.show() - show panel
        // menu.panel.hide() - hide panel
    }
});

Menu State Management

Custom State Updates

// Custom function to update specific menu states
function updateMenuStates() {
    const menus = editor.menus.menus;
    
    // Update bold menu state
    if (menus.bold && menus.bold.tryChangeActive) {
        menus.bold.tryChangeActive();
    }
    
    // Update italic menu state  
    if (menus.italic && menus.italic.tryChangeActive) {
        menus.italic.tryChangeActive();
    }
    
    // Update all menu states
    editor.menus.changeActive();
}

// Call after programmatic formatting
editor.cmd.do('bold');
updateMenuStates();

Menu State Monitoring

// Monitor menu state changes
function monitorMenuState(menuName) {
    const menu = editor.menus.menus[menuName];
    if (!menu || !menu.$elem) return;
    
    // Check if menu is active
    const isActive = menu.$elem.hasClass('w-e-active');
    console.log(`${menuName} is ${isActive ? 'active' : 'inactive'}`);
    
    return isActive;
}

// Usage
const isBold = monitorMenuState('bold');
const isItalic = monitorMenuState('italic');

// Monitor multiple menu states
function getActiveMenus() {
    const activeMenus = [];
    const menus = editor.menus.menus;
    
    Object.keys(menus).forEach(menuName => {
        if (monitorMenuState(menuName)) {
            activeMenus.push(menuName);
        }
    });
    
    return activeMenus;
}

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

Advanced Menu Interactions

Custom Menu Event Handlers

// Add custom behavior to existing menus
function enhanceMenus() {
    const menus = editor.menus.menus;
    
    // Enhance bold menu
    if (menus.bold && menus.bold.$elem) {
        menus.bold.$elem.on('click', function() {
            console.log('Bold menu clicked');
            // Custom analytics, validation, etc.
        });
    }
    
    // Enhance image menu
    if (menus.image && menus.image.$elem) {
        menus.image.$elem.on('click', function() {
            console.log('Image menu clicked');
            // Custom image handling logic
        });
    }
}

// Call after editor creation
editor.create();
enhanceMenus();

Menu Availability Checking

// Check which menus are available
function checkMenuAvailability() {
    const requiredMenus = ['bold', 'italic', 'link', 'image'];
    const availableMenus = Object.keys(editor.menus.menus);
    
    const missing = requiredMenus.filter(menu => !availableMenus.includes(menu));
    
    if (missing.length > 0) {
        console.warn('Missing required menus:', missing);
        return false;
    }
    
    console.log('All required menus are available');
    return true;
}

// Validate menu configuration
if (checkMenuAvailability()) {
    // Proceed with menu-dependent functionality
    console.log('Editor is properly configured');
} else {
    // Handle missing menus
    console.log('Some menus are missing from configuration');
}

Menu Synchronization

// Synchronize menu states with external UI
function syncWithExternalUI() {
    // Get current menu states
    const menuStates = {
        bold: monitorMenuState('bold'),
        italic: monitorMenuState('italic'),
        underline: monitorMenuState('underline')
    };
    
    // Update external UI elements
    Object.keys(menuStates).forEach(menuName => {
        const externalButton = document.getElementById(`external-${menuName}`);
        if (externalButton) {
            externalButton.classList.toggle('active', menuStates[menuName]);
        }
    });
}

// Sync on selection change
editor.customConfig.onchange = function() {
    setTimeout(syncWithExternalUI, 150);
};

// Manual sync
function manualSync() {
    editor.menus.changeActive();
    setTimeout(syncWithExternalUI, 100);
}

Complete Menus API Interface

interface MenusAPI {
  /** Collection of individual menu instances */
  menus: {[menuName: string]: MenuInstance};
  
  /** Update active state of all menu items */
  changeActive(): void;
}

interface MenuInstance {
  /** Menu interaction type */
  type: 'click' | 'droplist' | 'panel';
  
  /** Menu DOM element */
  $elem: Element;
  
  /** Update active state if supported */
  tryChangeActive?(): void;
  
  /** Click event handler */
  onClick?(event: Event): void;
  
  /** Dropdown list for droplist menus */
  droplist?: {
    show(): void;
    hide(): void;
    showTimeoutId?: number;
    hideTimeoutId?: number;
  };
  
  /** Panel for panel menus */
  panel?: {
    show(): void;
    hide(): void;
  };
}

Menu Configuration Integration

The menu system works closely with the configuration system. See Configuration for menu setup:

// Configure available menus
editor.customConfig.menus = [
    'head', 'bold', 'fontSize', 'fontName', 'italic', 'underline',
    'strikeThrough', 'foreColor', 'backColor', 'link', 'list',
    'justify', 'quote', 'emoticon', 'image', 'table', 'video',
    'code', 'undo', 'redo'
];

// Create editor
editor.create();

// Access configured menus
const configuredMenus = Object.keys(editor.menus.menus);
console.log('Configured menus:', configuredMenus);

Install with Tessl CLI

npx tessl i tessl/npm-wangeditor

docs

commands.md

configuration.md

content-operations.md

editor-management.md

image-upload.md

index.md

menus.md

selection.md

tile.json