Full-featured WYSIWYG Editor with RTL Support - BarnamenevisEditor

File Size: 2.45 MB
Views Total: 1
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Full-featured WYSIWYG Editor with RTL Support - BarnamenevisEditor

BarnamenevisEditor is a lightweight, fully-featured rich text editor built on top of the latest jQuery library and Bootstrap 5 framework.

It transforms a standard textarea into a WYSIWYG editor that handles bidirectional text, custom fonts, and modern dark mode interfaces out of the box.

Features:

  • Text Formatting: Bold, italic, underline, strikethrough, font family selection, font size control, text color, background color, and clear formatting tools.
  • Bidirectional Text Support: Proper LTR/RTL switching at both inline and block levels. Suitable for Arabic, Persian, Hebrew, and mixed-language content without layout corruption.
  • Built-in Localization System: Ships with English and Persian language files, with a straightforward pattern for adding additional languages through namespaced translation objects.
  • Color Management: 64-color default palette with live indicator bars that reflect the current text or background color, plus automatic reset when no color is applied.
  • Table Management: Full table insertion and editing capabilities with proper cell selection.
  • Keyboard Shortcuts: Standard shortcuts for bold, italic, underline, undo, redo, and tab indentation work as expected across browsers.
  • Status Bar with Metrics: Real-time word and character counts that update as users type, with proper singular and plural forms based on the active language.
  • Dark Mode Support: Automatic theming through a CSS class toggle that styles the toolbar, content area, modals, and status bar consistently.
  • Bootstrap 5: Uses Bootstrap's grid, buttons, modals, and form controls, so the editor inherits your site's existing Bootstrap theme without additional styling work.

How To Use It:

1. Include the required Bootstrap 5 framework, Bootstrap Icons, and jQuery library in your HTML document.

<!-- jQuery is required -->
<script src="/path/to/cdn/jquery.min.js"></script>

<!-- Bootstrap Framework -->
<link rel="stylesheet" href="/path/to/cdn/bootstrap.min.css" />
<script src="/path/to/cdn/bootstrap.bundle.min.js"></script>

<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.13.1/font/bootstrap-icons.min.css" />

2. Download the plugin and load the following files in the document.

<link rel="stylesheet" href="css/BarnamenevisEditor.css">
<script src="js/BarnamenevisEditor.js"></script>

<!-- Optional: for localization -->
<script src="js/lang/en.js"></script> 
<script src="js/lang/fa.js"></script> 

3. Place a <textarea> in your HTML with a unique ID. The editor will attach to this element.

<textarea id="myEditor">
  ...
</textarea>

4. Initialize the editor after the DOM loads. The editor replaces the textarea in place and syncs the HTML content back to a hidden field for form submission.

$(function () {
  $('#myEditor').barnamenevisEditor({
    // options here
  });
});

5. Customize the editor with a configuration object during initialization.

  • height: (String) Sets the height of the editable area (e.g., '400px').
  • language: (String) Defines the UI language using a language code (e.g., 'en').
  • toolbar: (String|Array) Configures the toolbar layout. Use presets ('full', 'basic', 'minimal') or a custom nested array of button IDs.
  • fontFamilies: (Array) An array of font names to override the default font selection dropdown.
  • fontSizes: (Array) An array of numbers (1-7) to map to the browser's font size levels.
  • colors: (Array) An array of hex color codes to customize the color palette.
  • showStatusBar: (Boolean) Toggles the visibility of the status bar that shows word and character counts.
  • placeholder: (String) Sets the placeholder text that appears when the editor is empty.
  • theme: (String) Sets the visual theme. Options include 'bootstrap', 'dark', and 'light'.
  • onInit: (Function) A callback function that runs after the editor is fully initialized.
  • onChange: (Function) A callback function that runs whenever the editor's content changes.
$('#myEditor').barnamenevisEditor({
  height: '400px',
  theme: 'bootstrap', // bootstrap, dark, light
  toolbar: 'full', // full, basic, minimal, or custom array
  language: 'en', // Default language
  fontSizes: [1, 2, 3, 4, 5, 6, 7],
  fontFamilies: [
    'Arial',
    'Courier New',
    'Georgia',
    'Times New Roman',
    'Trebuchet MS',
    'Verdana',
    'Comic Sans MS',
    'Impact',
    // You can also use objects with displayName and value:
    // { displayName: 'میخک (Mikhak)', value: 'Mikhak, Tahoma, sans-serif' },
    // { displayName: 'My Custom Font', value: 'CustomFont, Arial, sans-serif' }
  ],
  colors: [
    '#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF',
    '#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF',
    '#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE',
    '#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD',
    '#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5',
    '#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B',
    '#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842',
    '#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031'
  ],
  onChange: null,
  onInit: null,
  showStatusBar: true,
  placeholder: null // Will be set from language file
});

6. If the preset toolbar options don't fit your needs, pass a nested array of button identifiers to build your own toolbar layout. Each sub-array creates a button group. Available button identifiers: undo, redo, bold, italic, underline, strikethrough, removeFormat, fontname, fontsize, forecolor, backcolor, insertUnorderedList, insertOrderedList, justifyLeft, justifyCenter, justifyRight, justifyFull, directionLTR, directionRTL, paragraphLTR, paragraphRTL, insertLink, insertImage, insertTable, codeView, and fullscreen.

$('#myEditor').barnamenevisEditor({
  toolbar: [
    ['undo', 'redo'],
    ['bold', 'italic', 'underline', 'strikethrough'],
    ['forecolor', 'backcolor'],
    ['insertLink', 'insertImage', 'insertTable'],
    ['codeView', 'fullscreen']
  ]
});

7. To use fonts beyond the defaults, load the font files first, then pass a fontFamilies array. When you specify this option, your list completely replaces the built-in fonts. The object format lets you show localized display names while specifying proper font stacks with fallbacks in the value property. Always include fallback fonts because users who don't have the primary font installed will see the next available option.

$('#myEditor').barnamenevisEditor({
  language: 'fa',
  fontFamilies: [
    'Arial',
    { displayName: 'وزیر (Vazir)', value: 'Vazirmatn, sans-serif' }
    { displayName: 'Roboto', value: 'Roboto, Arial, sans-serif' }
  ]
});

8. API methods:

// Get or set content
$('#myEditor').barnamenevisEditor('getContent');
$('#myEditor').barnamenevisEditor('setContent', '<p>New content!</p>');

// Get plain text
$('#myEditor').barnamenevisEditor('getText');

// Control editor state
$('#myEditor').barnamenevisEditor('clear');
$('#myEditor').barnamenevisEditor('focus');
$('#myEditor').barnamenevisEditor('disable');
$('#myEditor').barnamenevisEditor('enable');
$('#myEditor').barnamenevisEditor('destroy');

// Toggle Dark Mode
$('.editor-wrapper').toggleClass('theme-dark');

9. Events:

$('#myEditor')
  .on('barnameneviseditor.init', (evt, instance) => console.log('Editor is ready.'))
  .on('barnameneviseditor.change', (evt, html) => console.log('Content changed:', html))
  .on('barnameneviseditor.focus', () => console.log('Editor focused.'))
  .on('barnameneviseditor.blur', () => console.log('Editor blurred.'));

10. The localization system uses namespaced objects stored in window.BarnamenevisEditor.lang. To add a language, create a new JavaScript file that follows the same structure as the included English or Persian language files.

(function() {
  'use strict';

  if (typeof window.BarnamenevisEditor === 'undefined') {
    window.BarnamenevisEditor = {};
  }

  window.BarnamenevisEditor.lang = window.BarnamenevisEditor.lang || {};

  window.BarnamenevisEditor.lang.en = {
    // Toolbar buttons
    toolbar: {
      undo: 'Undo (Ctrl+Z)',
      redo: 'Redo (Ctrl+Y)',
      bold: 'Bold (Ctrl+B)',
      italic: 'Italic (Ctrl+I)',
      underline: 'Underline (Ctrl+U)',
      strikethrough: 'Strikethrough',
      fontname: 'Font Family',
      fontsize: 'Font Size',
      forecolor: 'Text Color',
      backcolor: 'Background Color',
      removeFormat: 'Clear Formatting',
      insertUnorderedList: 'Bulleted List',
      insertOrderedList: 'Numbered List',
      justifyLeft: 'Align Left',
      justifyCenter: 'Align Center',
      justifyRight: 'Align Right',
      justifyFull: 'Justify',
      insertLink: 'Insert Link',
      insertImage: 'Insert Image',
      insertTable: 'Insert Table',
      codeView: 'Code View',
      fullscreen: 'Fullscreen',
      directionLTR: 'Inline Left to Right',
      directionRTL: 'Inline Right to Left',
      paragraphLTR: 'Paragraph Left to Right',
      paragraphRTL: 'Paragraph Right to Left'
    },

    // Font sizes
    fontSizeLabel: 'Font Size',
    fontSize: {
      1: 'Size 1',
      2: 'Size 2',
      3: 'Size 3',
      4: 'Size 4',
      5: 'Size 5',
      6: 'Size 6',
      7: 'Size 7'
    },

    // Modals
    modal: {
      // Link modal
      insertLink: 'Insert Link',
      linkText: 'Link Text:',
      linkUrl: 'URL:',
      linkNewTab: 'Open in new tab',
      linkTextPlaceholder: 'Enter link text',
      linkUrlPlaceholder: 'https://example.com',
      
      // Image modal
      insertImage: 'Insert Image',
      imageUrl: 'Image URL:',
      imageAlt: 'Alt Text:',
      imageWidth: 'Width (optional):',
      imageUrlPlaceholder: 'https://example.com/image.jpg',
      imageAltPlaceholder: 'Image description',
      imageWidthPlaceholder: 'e.g., 300px or 100%',
      
      // Table modal
      insertTable: 'Insert Table',
      tableSelectSize: 'Select table size:',
      
      // Common
      cancel: 'Cancel',
      insert: 'Insert',
      close: 'Close'
    },

    // Status bar
    statusBar: {
      words: 'words',
      word: 'word',
      characters: 'characters',
      character: 'character'
    },

    // Alerts and messages
    messages: {
      enterUrl: 'Please enter a URL',
      enterImageUrl: 'Please enter an image URL',
      contentCopied: 'HTML copied to clipboard!',
      browserNotSupported: 'Your browser does not support this feature',
      blogPostSaved: 'Blog post saved!',
      success: 'Success',
      info: 'Information',
      error: 'Error',
      ok: 'OK'
    },

    // Placeholder
    placeholder: 'Start typing...'
  };

})();

FAQs:

Q: Why doesn't my custom font appear in the editor even though I've added it to fontFamilies?
A: Check three things in order. First, confirm the font file actually loads by opening Developer Tools, going to the Network tab, filtering by Font, and refreshing the page. If the font file doesn't appear, your CSS @font-face declaration is wrong or the path is incorrect. Second, verify the exact spelling of the font name matches between your CSS declaration and the fontFamilies value property. Font names are case-sensitive. Third, make sure you loaded the font stylesheet before initializing the editor, because the editor needs the font to be available when it renders the dropdown options.

Q: How do I retrieve the editor content when submitting a form via AJAX instead of a standard form submission?
A: Call $('#editor').barnamenevisEditor('getContent') to get the HTML string, then include it in your AJAX payload. The hidden input field that syncs automatically only works for standard form submissions. For AJAX submissions, you need to manually grab the content and add it to your request data object.

Q: Can I initialize multiple editors on the same page with different configurations?
A: Yes, just call barnamenevisEditor() on different selectors with different option objects. Each editor instance maintains its own state independently. If you need to initialize several editors with similar configurations, consider storing a config object and passing it to each initialization call rather than duplicating the options inline.

Q: The editor content looks wrong when I switch between LTR and RTL languages mid-paragraph. What's the correct approach?
A: Use the inline direction buttons (directionLTR, directionRTL) for small sections of opposite-direction text within a paragraph. Use the block direction buttons (paragraphLTR, paragraphRTL) when you want to change the direction of an entire paragraph or larger block element. The browser's Unicode bidirectional algorithm handles most mixed-direction scenarios automatically if you set the block direction correctly.

Related Resources:


This awesome jQuery plugin is developed by delphiassistant. For more Advanced Usages, please check the demo page or visit the official website.