Trumbowyg.js: Lightweight WYSIWYG Editor Plugin For jQuery

File Size: 202 KB
Views Total: 32957
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Trumbowyg.js: Lightweight WYSIWYG Editor Plugin For jQuery

Trumbowyg is a lightweight jQuery WYSIWYG rich text editor that turns a textarea or editable container into a configurable HTML editor with formatting controls, semantic markup, localization, plugins, and a jQuery API.

It's great for CMS fields, admin panels, comment forms, and other UIs that need visual HTML editing inside an existing jQuery project.

Features

  • Configurable WYSIWYG toolbar with HTML source view, formatting, links, images, lists, alignment, and fullscreen mode.
  • Semantic HTML conversion with configurable tag handling and tag-specific CSS classes.
  • Plugin system for colors, fonts, tables, uploads, media embeds, image resizing, mentions, paste handling, and more.
  • More than 45 localization files, with English built into the core editor.
  • SVG editor icons with configurable sprite paths and support for custom skins.
  • jQuery API for reading and writing HTML, managing selections, opening modals, changing editor state, and destroying an instance.
  • Editor events for initialization, focus, blur, content changes, paste, resize, fullscreen mode, and modal lifecycle.

Alternatives And Related Resources

Installation

Install Trumbowyg with npm, or download the distribution files and load them directly in the browser.

# npm
npm install trumbowyg

Trumbowyg requires jQuery 1.8 or newer. Load the editor stylesheet, jQuery, and Trumbowyg in this order.

<link rel="stylesheet" href="trumbowyg/dist/ui/trumbowyg.min.css">

<script src="jquery.min.js"></script>
<script src="trumbowyg/dist/trumbowyg.min.js"></script>

How To Use Trumbowyg

Basic Setup

Add a textarea or container for the editor.

<textarea id="editor" name="content"></textarea>

Initialize Trumbowyg after jQuery and the editor script have loaded.

$('#editor').trumbowyg();

Use A Custom Toolbar

The btns option controls the toolbar groups and button order.

$('#editor').trumbowyg({
  btns: [
    ['viewHTML'],
    ['undo', 'redo'],
    ['formatting'],
    ['strong', 'em'],
    ['link'],
    ['insertImage'],
    ['unorderedList', 'orderedList'],
    ['fullscreen']
  ],
  autogrow: true
});

Load A Language Pack

English is included in the core editor. For another language, load its file after Trumbowyg and before initialization, then set lang.

<script src="trumbowyg/dist/langs/fr.min.js"></script>
$('#editor').trumbowyg({
  lang: 'fr'
});

Load A Plugin

Load plugin JavaScript after jQuery and Trumbowyg, but before the initialization code. Plugins with their own UI styles also require the matching CSS file.

<link rel="stylesheet" href="trumbowyg/dist/plugins/colors/ui/trumbowyg.colors.min.css">

<script src="jquery.min.js"></script>
<script src="trumbowyg/dist/trumbowyg.min.js"></script>
<script src="trumbowyg/dist/plugins/colors/trumbowyg.colors.min.js"></script>
$('#editor').trumbowyg({
  btns: [
    ['strong', 'em'],
    ['foreColor', 'backColor']
  ]
});

Bundled Plugins

Trumbowyg currently includes 27 bundled plugins. Some plugins register behavior as soon as their script loads. Button-based plugins also need their button name in the btns configuration.

  • Allow Tags From Paste: Keeps selected HTML tags when users paste formatted content.
  • Base 64: Inserts images as base64 data.
  • Clean Paste: Cleans pasted HTML before insertion.
  • Colors: Adds foreground and background color controls.
  • Emoji: Adds an emoji picker.
  • Font Family: Adds a font-family selector.
  • Font Size: Adds a font-size selector.
  • Giphy: Searches for and inserts GIFs from Giphy.
  • Highlight: Adds code highlighting support.
  • History: Adds history-based undo and redo buttons.
  • Indent: Adds indent and outdent controls.
  • Insert Audio: Inserts HTML audio content.
  • Line Height: Adds a line-height selector.
  • MathML: Adds MathML editing support.
  • Mention: Inserts users from a configurable source list.
  • Noembed: Embeds supported content from a URL through noembed.com.
  • Paste Embed: Converts pasted supported URLs into embedded content.
  • Paste Image: Inserts clipboard images as base64 data.
  • Preformatted: Wraps code content in preformatted markup.
  • Resizimg: Adds drag handles for image resizing. This plugin also requires jquery-resizable.
  • Ruby: Adds ruby text markup controls.
  • Special Chars: Adds a special-character picker.
  • Speech Recognition: Inserts text from browser speech recognition.
  • Table: Creates and manages tables, rows, columns, cell merging, and table colors.
  • Template: Inserts predefined HTML templates.
  • Tenor: Searches for and inserts GIFs from Tenor.
  • Upload: Uploads an image to a server and inserts the returned URL into the editor.

Core Configuration Options

$('#editor').trumbowyg({
  lang: 'en',
  fixedBtnPane: false,
  fixedFullWidth: false,
  autogrow: false,
  autogrowOnEnter: false,
  imageWidthModalEdit: false,
  hideButtonTexts: null,

  prefix: 'trumbowyg-',
  tagClasses: {},

  semantic: true,
  semanticKeepAttributes: false,
  resetCss: false,
  removeformatPasted: false,
  tabToIndent: false,
  tagsToRemove: [],
  tagsToKeep: ['hr', 'img', 'embed', 'iframe', 'input'],

  btns: [
    ['viewHTML'],
    ['undo', 'redo'],
    ['formatting'],
    ['strong', 'em', 'del'],
    ['superscript', 'subscript'],
    ['link'],
    ['insertImage'],
    ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
    ['unorderedList', 'orderedList'],
    ['horizontalRule'],
    ['removeformat'],
    ['fullscreen']
  ],

  btnsDef: {},
  changeActiveDropdownIcon: false,

  inlineElementsSelector: 'a,abbr,acronym,b,caption,cite,code,col,dfn,dir,dt,dd,em,font,hr,i,kbd,li,q,span,strikeout,strong,sub,sup,u',

  pasteHandlers: [],
  plugins: {},

  urlProtocol: false,
  minimalLinks: false,
  linkTargets: ['_self', '_blank'],

  svgPath: null
});

URL Protocol

urlProtocol controls how Trumbowyg handles links that do not already include a protocol. The default value is false. Set it to true to prefix bare domains with https://, or pass a protocol string such as 'ftp'.

$('#editor').trumbowyg({
  urlProtocol: true
});

For example, example.com becomes https://example.com. Anchor links, email addresses, and relative URLs are left unchanged.

Link Targets

linkTargets controls the target choices shown for links. The first entry is the default target. Current defaults are ['_self', '_blank'].

$('#editor').trumbowyg({
  linkTargets: ['_blank', '_self', '_parent', '_top']
});

Older Trumbowyg releases used defaultLinkTarget. Current configurations should use linkTargets.

Minimal Link Dialog

Set minimalLinks to true to keep only the URL and text fields in the link dialog.

$('#editor').trumbowyg({
  minimalLinks: true
});

Tag Classes

The tagClasses option assigns CSS classes to generated tags.

$('#editor').trumbowyg({
  tagClasses: {
    h2: 'content-heading',
    blockquote: 'content-quote',
    table: 'content-table'
  }
});

Plugin Configuration Reference

The following settings cover the plugin configuration already used on this page. Plugins that expose no configuration only need their script and, when applicable, a toolbar button.

// Allow Tags From Paste
// When empty, all tags are allowed making this plugin useless
// If you want to remove all tags, use removeformatPasted core option instead
allowedTags: [],
// List of tags which can be allowed
removableTags: [
  'a',
  'abbr',
  'address',
  'b',
  'bdi',
  'bdo',
  'blockquote',
  'br',
  'cite',
  'code',
  'del',
  'dfn',
  'details',
  'em',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
  'hr',
  'i',
  'ins',
  'kbd',
  'mark',
  'meter',
  'pre',
  'progress',
  'q',
  'rp',
  'rt',
  'ruby',
  's',
  'samp',
  'small',
  'span',
  'strong',
  'sub',
  'summary',
  'sup',
  'time',
  'u',
  'var',
  'wbr',
  'img',
  'map',
  'area',
  'canvas',
  'figcaption',
  'figure',
  'picture',
  'audio',
  'source',
  'track',
  'video',
  'ul',
  'ol',
  'li',
  'dl',
  'dt',
  'dd',
  'table',
  'caption',
  'th',
  'tr',
  'td',
  'thead',
  'tbody',
  'tfoot',
  'col',
  'colgroup',
  'style',
  'div',
  'p',
  'form',
  'input',
  'textarea',
  'button',
  'select',
  'optgroup',
  'option',
  'label',
  'fieldset',
  'legend',
  'datalist',
  'keygen',
  'output',
  'iframe',
  'link',
  'nav',
  'header',
  'hgroup',
  'footer',
  'main',
  'section',
  'article',
  'aside',
  'dialog',
  'script',
  'noscript',
  'embed',
  'object',
  'param'
]

// Colors
colorList: [
  'ffffff', '000000', 'eeece1', '1f497d', '4f81bd', 'c0504d', '9bbb59', '8064a2', '4bacc6', 'f79646', 'ffff00',
  'f2f2f2', '7f7f7f', 'ddd9c3', 'c6d9f0', 'dbe5f1', 'f2dcdb', 'ebf1dd', 'e5e0ec', 'dbeef3', 'fdeada', 'fff2ca',
  'd8d8d8', '595959', 'c4bd97', '8db3e2', 'b8cce4', 'e5b9b7', 'd7e3bc', 'ccc1d9', 'b7dde8', 'fbd5b5', 'ffe694',
  'bfbfbf', '3f3f3f', '938953', '548dd4', '95b3d7', 'd99694', 'c3d69b', 'b2a2c7', 'b7dde8', 'fac08f', 'f2c314',
  'a5a5a5', '262626', '494429', '17365d', '366092', '953734', '76923c', '5f497a', '92cddc', 'e36c09', 'c09100',
  '7f7f7f', '0c0c0c', '1d1b10', '0f243e', '244061', '632423', '4f6128', '3f3151', '31859b', '974806', '7f6000'
],
foreColorList: null, // fallbacks on colorList
backColorList: null, // fallbacks on colorList
allowCustomForeColor: true,
allowCustomBackColor: true,
displayAsList: false,

// Font Family
fontList: [
  {name: 'Arial', family: 'Arial, Helvetica, sans-serif'},
  {name: 'Arial Black', family: 'Arial Black, Gadget, sans-serif'},
  {name: 'Comic Sans', family: 'Comic Sans MS, Textile, cursive, sans-serif'},
  {name: 'Courier New', family: 'Courier New, Courier, monospace'},
  {name: 'Georgia', family: 'Georgia, serif'},
  {name: 'Impact', family: 'Impact, Charcoal, sans-serif'},
  {name: 'Lucida Console', family: 'Lucida Console, Monaco, monospace'},
  {name: 'Lucida Sans', family: 'Lucida Sans Uncide, Lucida Grande, sans-serif'},
  {name: 'Palatino', family: 'Palatino Linotype, Book Antiqua, Palatino, serif'},
  {name: 'Tahoma', family: 'Tahoma, Geneva, sans-serif'},
  {name: 'Times New Roman', family: 'Times New Roman, Times, serif'},
  {name: 'Trebuchet', family: 'Trebuchet MS, Helvetica, sans-serif'},
  {name: 'Verdana', family: 'Verdana, Geneva, sans-serif'}
]

// Font Size
sizeList: [
  'x-small',
  'small',
  'medium',
  'large',
  'x-large'
],
allowCustomSize: true

// Giphy
{
  rating: 'g',
  apiKey: null,
  throttleDelay: 300,
  noResultGifUrl: 'https://media.giphy.com/media/2Faz9FbRzmwxY0pZS/giphy.gif'
};

// Insert Audio
src: {
  label: 'URL',
  required: true
},
autoplay: {
  label: 'AutoPlay',
  required: false,
  type: 'checkbox'
},
muted: {
  label: 'Muted',
  required: false,
  type: 'checkbox'
},
preload: {
  label: 'preload options',
  required: false
}

// Line Height
sizeList: [
  '0.9',
  'normal',
  '1.5',
  '2.0'
]

// Mention
source: [],
formatDropdownItem: formatDropdownItem,
formatResult: formatResult

// Noembed
proxy: 'https://noembed.com/embed?nowrap=on',
urlFiled: 'url',
data: [],
success: undefined,
error: undefined

// Paste Embed
enabled: true,
endpoints: [
  'https://noembed.com/embed?nowrap=on',
  'https://api.maxmade.nl/url2iframe/embed'
]

// Resizimg
minSize: 32,
step: 4,

// Special Chars
symbolList: [
  // currencies
  '0024', '20AC', '00A3', '00A2', '00A5', '00A4', '2030', null,
  // legal signs
  '00A9', '00AE', '2122', null,
  // textual sign
  '00A7', '00B6', '00C6', '00E6', '0152', '0153', null,
  '2022', '25CF', '2023', '25B6', '2B29', '25C6', null,
  //maths
  '00B1', '00D7', '00F7', '21D2', '21D4', '220F', '2211', '2243', '2264', '2265'
]

// Table
rows: 8,
columns: 8,
allowHorizontalResize: true,
colorList: [
  'ffffff', '000000', 'eeece1', '1f497d', '4f81bd', 'c0504d', '9bbb59', '8064a2', '4bacc6', 'f79646', 'ffff00',
  'f2f2f2', '7f7f7f', 'ddd9c3', 'c6d9f0', 'dbe5f1', 'f2dcdb', 'ebf1dd', 'e5e0ec', 'dbeef3', 'fdeada', 'fff2ca',
  'd8d8d8', '595959', 'c4bd97', '8db3e2', 'b8cce4', 'e5b9b7', 'd7e3bc', 'ccc1d9', 'b7dde8', 'fbd5b5', 'ffe694',
  'bfbfbf', '3f3f3f', '938953', '548dd4', '95b3d7', 'd99694', 'c3d69b', 'b2a2c7', 'b7dde8', 'fac08f', 'f2c314',
  'a5a5a5', '262626', '494429', '17365d', '366092', '953734', '76923c', '5f497a', '92cddc', 'e36c09', 'c09100',
  '7f7f7f', '0c0c0c', '1d1b10', '0f243e', '244061', '632423', '4f6128', '3f3151', '31859b', '974806', '7f6000'
],
backgroundColorList: null, // fallbacks on colorList
allowCustomBackgroundColor: true,
displayBackgroundColorsAsList: false,
borderColorList: null, // fallbacks on colorList
allowCustomBorderColor: true,
displayBorderColorsAsList: false,
dropdown: [
  {
      title: 'tableRows',
      buttons: [
          'tableAddHeaderRow',
          'tableAddRowAbove',
          'tableAddRow',
          'tableDeleteRow',
      ],
  },
  {
      title: 'tableColumns',
      buttons: [
          'tableAddColumnLeft',
          'tableAddColumn',
          'tableDeleteColumn',
      ],
  },
  {
      title: 'tableVerticalAlign',
      buttons: [
          'tableVerticalAlignTop',
          'tableVerticalAlignMiddle',
          'tableVerticalAlignBottom',
     ],
  },
  {
      title: 'tableOthers',
      buttons: [
          // Cell merge/split
          'tableMergeCells',
          'tableUnmergeCells',
          'tableDestroy',
      ]
  }
],

// Upload
serverPath: '',
fileFieldName: 'fileToUpload',
data: [],                       // Additional data for ajax [{name: 'key', value: 'value'}]
headers: {},                    // Additional headers
xhrFields: {},                  // Additional fields
urlPropertyName: 'file',        // How to get url from the json response (for instance 'url' for {url: ....})
statusPropertyName: 'success',  // How to get status from the json response
success: undefined,             // Success callback: function (data, trumbowyg, $modal, values) {}
error: undefined,               // Error callback: function () {}
imageWidthModalEdit: false      // Add ability to edit image width

Speech Recognition

$('#editor').trumbowyg({
  btns: [
    ['speechrecognition']
  ],
  plugins: {
    speechrecognition: {
      lang: 'en-GB'
    }
  }
});

API Methods

// Open a modal.
var $modal = $('#editor').trumbowyg('openModal', {
  title: 'Editor Settings',
  content: '

Custom modal content

' }); // Close the current modal. $('#editor').trumbowyg('closeModal'); // Build a modal from input definitions. $('#editor').trumbowyg('openModalInsert', { title: 'Insert Link Data', fields: { url: { label: 'URL', required: true } }, callback: function (values) { console.log(values.url); return true; } }); // Save and restore the current selection range. $('#editor').trumbowyg('saveRange'); $('#editor').trumbowyg('restoreRange'); // Get the current range. var range = $('#editor').trumbowyg('getRange'); // Get text from the last saved range. var selectedText = $('#editor').trumbowyg('getRangeText'); // Get editor HTML. var content = $('#editor').trumbowyg('html'); // Replace editor HTML. $('#editor').trumbowyg('html', '

Updated content

'); // Remove all editor content. $('#editor').trumbowyg('empty'); // Disable or enable editing. $('#editor').trumbowyg('disable'); $('#editor').trumbowyg('enable'); // Toggle HTML and WYSIWYG views. $('#editor').trumbowyg('toggle'); // Destroy the editor and restore the original element. $('#editor').trumbowyg('destroy');

Events

Trumbowyg triggers editor events on the jQuery element used to create the editor.

$('#editor')
  .trumbowyg()
  .on('tbwfocus', function () {
    // Editor received focus.
  })
  .on('tbwblur', function () {
    // Editor lost focus.
  })
  .on('tbwinit', function () {
    // Editor initialized.
  })
  .on('tbwchange', function () {
    // Editor content changed.
  })
  .on('tbwresize', function () {
    // Autogrow changed the editor size.
  })
  .on('tbwpaste', function () {
    // Content was pasted.
  })
  .on('tbwopenfullscreen', function () {
    // Fullscreen mode opened.
  })
  .on('tbwclosefullscreen', function () {
    // Fullscreen mode closed.
  })
  .on('tbwclose', function () {
    // Editor closed.
  })
  .on('tbwmodalopen', function () {
    // A Trumbowyg modal opened.
  })
  .on('tbwmodalclose', function () {
    // A Trumbowyg modal closed.
  });

Advanced Examples

Get And Save HTML Content

Use the html method as a getter before sending editor content through your existing form or AJAX workflow.

$('#save-post').on('click', function () {
  var htmlContent = $('#editor').trumbowyg('html');

  $('#content-field').val(htmlContent);
});

Clean Pasted Content

The core removeformatPasted option strips formatting from pasted content. The Clean Paste plugin provides a separate cleanup path for pasted HTML.

$('#editor').trumbowyg({
  removeformatPasted: true
});

Add Image Upload

The Upload plugin sends the selected image to your server and expects a JSON response that contains the uploaded file URL.

$('#editor').trumbowyg({
  btns: [
    ['strong', 'em'],
    ['upload']
  ],
  plugins: {
    upload: {
      serverPath: '/uploads/editor-image',
      fileFieldName: 'fileToUpload',
      urlPropertyName: 'file',
      statusPropertyName: 'success'
    }
  }
});

FAQs

Q: How do I add https:// to links that users enter without a protocol?
A: Set urlProtocol: true. Trumbowyg then prefixes bare domains with https://. You can also pass a custom protocol string.

Q: What replaced defaultLinkTarget?
A: Use linkTargets. The first item in the array acts as the default target, and the current default list is ['_self', '_blank'].

Q: How do I get or replace the editor HTML?
A: Call $('#editor').trumbowyg('html') to read the HTML. Pass HTML as the second argument to replace the current content.

Q: Why do Trumbowyg SVG icons fail to load?
A: Check the SVG asset path and cross-origin requests first. Trumbowyg can also use a custom svgPath when the automatic sprite path does not match your asset layout.

Changelog:

v2.31.0 (2025-03-03)

  • Make icons hidden without importing trumbowyg.css
  • Fix tagClasses to make it work in any cases
  • Fix modal select by adding/fixing id and name
  • Fix modal close when pressing Escape

v2.30.0 (2025-01-30)

  • Adjust style to be compatible with 2 latest versions of each browser or usage > 1%
  • Upgrade SCSS files to match the latest version
  • New Speech Recognition plugin
  • New Tenor plugin
  • New Giphy plugin

v2.29.0 (2025-01-29)

  • Bugfix for Table plugin

v2.28.0 (2023-03-07)

  • Bugfix

v2.27.3 (2023-03-01)

  • Bugfix

v2.27.0/1/2 (2023-02-28)

  • Table plugin rework
  • Feat: change editor HTML structure to allow overlays
  • Feat: add .trumbowyg-icons class for plugin SVG Sprites
  • Upgrade: use Array.isArray instead of deprecated $.isArray
  • Add Azerbaijani support
  • Update Catalan and Spanish core and plugins translations
  • Bugfixes

v2.26.0 (2022-11-15)

  • Breaking Change: Replace defaultLinkTarget option with linkTargets list
  • Feat: Add the ability to create select in modal
  • Feat: Add a select to pick the link target in the insert link modal
  • Bugfixes

v2.25.2 (2022-08-12)

  • Add Russian translations to all plugin
  • Add Belarusian translations to all plugin
  • Fix: do not disable removeformatPasted when the plugin is disabled itself
  • Prevent Firefox from nesting multiple spans on font-size changes
  • Fixes "Cannot read property '1' of null"
  • Make MathML editable, even after toggle HTML view

v2.25.1 (2021-07-15)

  • Prevent error when range does not exist

v2.25.0 (2021-07-05)

  • Fixed: Disable buttons when the editor is disabled

v2.24.0 (2021-06-08)

  • Fixed: Disable buttons when the editor is disabled
  • Add Estonian support
  • Add Bangla support
  • Add Spanish translations to table plugin
  • Add Turkish translations to some plugins
  • Plugins update

v2.23.0 (2020-12-07)

  • Add tagClasses option to add classes to any tag
  • Add Plugin indent: button indent & outdent

v2.22.0 (2020-11-26)

  • Lot of fixes

v2.21.0 (2019-12-31)

  • Properly clean body events on destroy
  • Add resize handle with canvas

v2.20.0 (2019-11-05)

  • Add tbwmodalopen and tbwmodalclose events
  • Add defaultLinkTarget option
  • Fixed Wrap cursor in p when empty
  • Add throttleDelay option and noResultGifUrl option to Giphy plugin

v2.19.0 (2019-09-02)

  • Set list-style decimal for ordoned lists in resetCss
  • Avoid 1px move on editor switch
  • Disable word wrapping in dropdowns
  • Restore close modal on escape
  • Add missing skipTrumbowyg to execCmd API binding
  • Fix Thai key from de to th
  • Add Add row above and change Add columns to Add columns to the left/right
  • Fix Font family bug when selecting a font with a space in the name
  • Fix color minification issue by using rgba instead of HEX+alpha

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