-
Notifications
You must be signed in to change notification settings - Fork 2
Advanced Features
Deep dive into Neiki's Editor's advanced capabilities β tables, images, themes, find & replace, autosave, and more.
Insert tables via the Table toolbar button. A dialog lets you set:
- Rows β number of rows
- Columns β number of columns
-
Header row β optional first row styled as
<th>
Right-click on any table cell to access a context menu with these options:
| Action | Description |
|---|---|
| Insert Row Above | Add a row above the current cell |
| Insert Row Below | Add a row below the current cell |
| Insert Column Left | Add a column to the left |
| Insert Column Right | Add a column to the right |
| Delete Row | Remove the current row |
| Delete Column | Remove the current column |
| Delete Table | Remove the entire table |
| Merge Cells | Merge selected cells horizontally (uses colspan) |
| Split Cell | Split a previously merged cell back to individual cells |
Tip
To select multiple cells for merging, click the first cell, then hold Shift and click the last cell in the same row. Then right-click to access "Merge Cells".
Hover near the border between two columns β a vertical drag handle appears. Drag it horizontally to resize adjacent columns:
- The table switches to
table-layout: fixedduring resize - All cells in the affected columns are resized proportionally
- Minimum column width is 40px to prevent collapse
Tip
Column resize works on both <td> and <th> cells. The handle appears when the cursor is within 6px of a column border.
Tables are rendered with default styling provided by neiki-editor.css:
- Bordered cells with subtle grid lines
- Header row with distinct background color
- Responsive width (100% of editor)
- Compatible with all built-in themes
Neiki's Editor supports five ways to insert images:
Click the Image toolbar button, paste a URL, and the image is inserted as a standard <img> tag.
<img src="https://example.com/photo.jpg" alt="Description">The image dialog includes a file picker that supports multiple file selection. Select one or more images and they will all be inserted into the editor.
Without imageUploadHandler:
- Images are read via
FileReaderAPI and converted to base64 data URIs - Each selected image is embedded directly in the HTML content
With imageUploadHandler:
- Each file is passed to your async handler which uploads it to a server/CDN
- The returned URL is inserted as a standard
<img src="...">tag - This keeps HTML content lightweight and enables browser caching
new NeikiEditor('#editor', {
imageUploadHandler: async (file) => {
const formData = new FormData();
formData.append('image', file);
const res = await fetch('/api/upload', { method: 'POST', body: formData });
const data = await res.json();
return data.url;
}
});Tip
Using imageUploadHandler is strongly recommended for production. It avoids bloated base64 content and allows browsers to cache large images efficiently.
Caution
Without imageUploadHandler, base64-encoded images increase the HTML content size significantly. For production use with large images, consider setting up the upload handler or using your own server-side processing.
Drag one or more image files directly into the editor content area. The editor automatically:
- Detects the drop event
- Uploads via
imageUploadHandler(if configured) or reads as base64 - Inserts each image at the drop position
Note
Multiple files dropped at once will each be inserted sequentially.
Selected text can also be dragged to a new position inside the editor. Text, image, and video drags share the same insertion indicator so the drop position is visible before release.
Copy an image to your clipboard (e.g. screenshot, right-click β Copy Image) and paste it directly into the editor with Ctrl+V.
- If
imageUploadHandleris configured, the image is uploaded and inserted as a URL - Otherwise, the image is embedded as base64
Click any image in the editor to select it. Resize handles appear on all four corners (NW, NE, SW, SE). Drag any handle to resize:
- Aspect ratio is always maintained during resize
- A live size label (e.g.
640 Γ 480) appears below the image - Minimum size is 30px wide to prevent accidental collapse
- Click outside the image to deselect and hide handles
Note
The resize wrapper is automatically cleaned up when calling getContent(), getHTML(), or getJSON() β only the <img> element with its inline width and height styles is included in the output.
When an image is selected, a contextual toolbar appears above it with image-specific actions:
| Button | Description |
|---|---|
| Drag handle (β Ώ) | Click and drag to reposition the image to a different location in the editor |
| Replace | Open a file picker to swap the current image (supports imageUploadHandler or base64) |
| Delete | Remove the selected image from the editor |
The floating text-formatting toolbar is automatically hidden when an image is selected, so only relevant image actions are shown.
Tip
To move an image, click it to select, then use the grip handle in the image toolbar to drag it to a new position. The image will be placed as a new block at the drop location.
Use Insert β Video to add videos by URL, from a local file, or by dragging a video file into the editor. Without videoUploadHandler, selected video files are converted to base64 and embedded in the HTML. With videoUploadHandler, the file is uploaded through your callback and the returned URL is inserted.
new NeikiEditor('#editor', {
videoUploadHandler: async (file) => {
const formData = new FormData();
formData.append('video', file);
const response = await fetch('/api/upload-video', { method: 'POST', body: formData });
const data = await response.json();
return data.url;
}
});Inserted videos render as <video controls>, are preserved by the sanitizer, and can be resized or repositioned like images.
Clean white background with dark text. Standard for most use cases.
Dark background with light text. Easy on the eyes for extended editing sessions.
A bright blue interface with a white editing canvas.
A deep blue interface for low-light editing with blue accents.
On initialization:
new NeikiEditor('#editor', {
theme: 'dark'
});Toggle at runtime:
editor.toggleTheme();Via the More menu (β―):
The default toolbar includes 'moreMenu' which contains a Change theme select for Light, Dark, Blue, and Dark Blue.
Set a specific theme:
editor.setTheme('dark');
editor.setTheme('light');
editor.setTheme('blue');
editor.setTheme('dark-blue');Important
The selected theme is persisted to localStorage as a global setting. This means:
- The theme choice applies to all editor instances on the page
- The theme persists across page reloads
- If a user selects dark mode, it remains dark even if you set
theme: 'light'in config β user preference takes priority
The dark theme applies the CSS class neiki-dark to the editor container. You can use this to style custom elements:
/* Custom styling for dark mode */
.neiki-dark .my-custom-element {
background: #1e1e1e;
color: #e0e0e0;
}Neiki's Editor supports multiple UI languages for all user-facing text.
| Code | Language |
|---|---|
en |
English (default) |
cs |
Czech |
zh |
Chinese |
es |
Spanish |
de |
German |
fr |
French |
pt |
Portuguese |
ja |
Japanese |
new NeikiEditor('#editor', {
language: 'cs' // Czech UI
});- All toolbar button tooltips
- Modal dialog labels (Link, Image, Table, Find & Replace)
- Status bar texts (word count, character count)
- Autosave messages ("Autosaving...", "Saved locally")
- System messages and confirmations
Note
The language option must be set at initialization. Changing language at runtime requires re-initializing the editor.
Open Find & Replace via the findReplace toolbar button. The bar appears at the top of the editor content area.
| Feature | Description |
|---|---|
| Search field | Type text to find in the editor content |
| Replace field | Type replacement text |
| Case Sensitive | Toggle button β when active, Hello β hello
|
| Regex Mode | Toggle button β enables regular expression patterns |
| Find Next | Jump to and highlight the next match |
| Replace | Replace the current highlighted match |
| Replace All | Replace every occurrence at once |
When Regex Mode is enabled, you can use powerful patterns:
| Pattern | Matches |
|---|---|
\b\w+\b |
Every word |
\d{4} |
4-digit numbers |
https?://\S+ |
URLs |
<em>.*?</em> |
Italic-wrapped text |
Tip
Regex mode uses JavaScript's RegExp under the hood. All standard regex syntax is supported, including character classes, quantifiers, and groups.
Autosave is accessible from the More menu (β―) in the default toolbar.
- User clicks Autosave in the More menu (β―)
- A badge shows the autosave status (β when active, β when inactive)
- Content is saved to
localStorageon content changes - The status bar shows "Autosaving..." / "Saved locally"
- On next page load, if autosave was enabled, content is restored automatically
Autosave storage is scoped by page URL and editor identity by default. If your app edits different records on the same URL, pass autosaveKey to isolate drafts explicitly:
new NeikiEditor('#editor', {
autosaveKey: 'article-42'
});- No automatic saves occur
- On page reload, the original content from the
<textarea>is shown (not old localStorage data) - This is the default behavior
Caution
Autosave is designed for development and testing purposes. For production applications, use the onChange callback to save content to your backend:
new NeikiEditor('#editor', {
onChange: debounce(function(content) {
fetch('/api/save', {
method: 'POST',
body: JSON.stringify({ content })
});
}, 2000)
});A context-sensitive toolbar that appears when text is selected.
| Position | Buttons | Description |
|---|---|---|
| Left | β² βΌ | Move current block up / down |
| Right |
B I U |
Bold, Italic, Underline, Strikethrough, Insert Link |
The move block buttons and formatting buttons are separated by a visual divider.
- Appears automatically above the text selection
- Follows the selection position
- Disappears when selection is cleared or the user clicks away
- Works alongside the main toolbar (both can be used)
- Move Up / Down reorders the top-level content block containing the selection
- When an image is selected, the floating toolbar is replaced by an image-specific toolbar with relevant actions
Note
The floating toolbar is always enabled and cannot be disabled or customized through configuration.
Hover over any content block to reveal a grip handle (β Ώ) on the left side. Drag to reorder blocks.
- Move the cursor near any top-level block (paragraph, heading, table, image, list, blockquote, etc.)
- A grip icon (β Ώ) appears on the left margin
- Click and drag the grip to move the block
- A ghost preview follows the cursor, and a dashed placeholder shows the drop position
- Release to drop the block at the new position
- Works with all top-level content blocks
- Ghost preview shows the block being dragged
- Drop placeholder with dashed border indicates target position
- Undo/Redo support β block moves are recorded in history
-
onChangecallback fires after each move
Tip
You can also use the Move Up / Move Down buttons in the floating toolbar for keyboard-friendly block reordering without dragging.
Click the Print toolbar button to print the editor content.
The print function:
- Opens a new browser window
- Copies the editor's HTML content with basic print styling
- Triggers the browser's native print dialog
- Closes the print window after printing
The printed output includes only the content β no toolbar, status bar, or editor chrome.
The status bar sits at the bottom of the editor and displays real-time information:
| Position | Content |
|---|---|
| Left | Word count and character count |
| Right | Autosave status (when enabled) and current block type (p, h1, h2, h3, etc.) |
The status bar updates automatically as you type or move the cursor.
editor.getContent(); // Get HTML string
editor.setContent('<p>Hello</p>'); // Set HTML content
editor.getText(); // Get plain text content
editor.isEmpty(); // Check if editor is empty
editor.getHTML(); // Alias for getContent()
editor.setHTML(html); // Alias for setContent()
editor.getJSON(); // Get structured JSON
editor.setJSON(json); // Set from JSONeditor.focus(); // Focus the editor
editor.blur(); // Blur the editor
editor.enable(); // Enable editing
editor.disable(); // Disable editing (read-only)
editor.destroy(); // Remove editor, restore textarea
editor.toggleFullscreen(); // Toggle fullscreen
editor.toggleTheme(); // Cycle through built-in themes
editor.setTheme('dark'); // Set specific theme
editor.triggerSave(); // Trigger onSave callback
editor.previewContent(); // Open preview modal
editor.downloadContent(); // Download content as HTML file
editor.clearAll(); // Clear all contenteditor.execCommand('bold'); // Execute any command
editor.insertHTML('<mark>hi</mark>'); // Insert HTML at cursor
editor.wrapSelection('mark', { class: 'hl' }); // Wrap selection
editor.unwrapSelection('mark'); // Unwrap selectioneditor.getSelection(); // Get Selection object- βοΈ Configuration β All config options
- π§ Toolbar Reference β All toolbar buttons
- π Plugin API β Extend with plugins
- π Integration Guide β PHP, Vue, React, AJAX
Getting Started
Reference
Extending
Integration
Features & UI
Project