Autocomplete Documentation
The optional Autocomplete plugin, introduced in CKEditor 4.10, provides contextual completion functionality for custom text matches based on user input. Every time the user types a pre-configured special character, such as @
or #
, they get information about available autocomplete suggestions displayed in a dedicated dropdown.
This feature is a base for implementing specialized autocomplete features, such as mentions, tags, emoji or custom implementations.
The following sample implements a few smart placeholders for Customer Care Service email responses. Start typing the name of one of the placeholders visible on the right side of the editor. Type [[
and accept the selected placeholder from the dropdown using the Enter or Tab key.
Related Features
Get Sample Source Code
- Autocomplete
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="robots" content="noindex, nofollow"> <title>Autocomplete</title> <script src="https://cdn.ckeditor.com/4.25.0-lts/standard-all/ckeditor.js"></script> </head> <body> <textarea cols="80" id="editor1" name="editor1" rows="10"><p>This is some <strong>sample text</strong>. You are using <a href="https://ckeditor.com/">CKEditor</a>.</p></textarea> <script> var PLACEHOLDERS = [{ id: 1, name: 'address', title: 'Address', description: 'Customer Support correspondence address.' }, { id: 2, name: 'assignee', title: 'Assignee Name', description: 'Ticket assignee name.' }, { id: 3, name: 'deadline', title: 'Deadline Time', description: 'Utmost time to which technician should handle the issue.' }, { id: 4, name: 'department', title: 'Department Name', description: 'Department name responsible for servicing this ticket.' }, { id: 5, name: 'caseid', title: 'Case ID', description: 'Unique case number used to distinguish tickets.' }, { id: 6, name: 'casename', title: 'Case Name', description: 'Name of the ticket provided by the user.' }, { id: 7, name: 'contact', title: 'Contact E-mail', description: 'Customer Support contact e-mail address.' }, { id: 8, name: 'customer', title: 'Customer Name', description: 'Receipent of your response.' }, { id: 9, name: 'hotline', title: 'Hotline Number', description: 'Customer Support Hotline number.' }, { id: 10, name: 'technician', title: 'Technician Name', description: 'Technician which will handle this ticket.' } ]; CKEDITOR.addCss('span > .cke_placeholder { background-color: #ffeec2; }'); CKEDITOR.replace('editor1', { plugins: 'autocomplete,textmatch,toolbar,wysiwygarea,basicstyles,link,undo,placeholder', toolbar: [{ name: 'document', items: ['Undo', 'Redo'] }, { name: 'basicstyles', items: ['Bold', 'Italic'] }, { name: 'links', items: ['Link', 'Unlink'] } ], on: { instanceReady: function(evt) { var itemTemplate = '<li data-id="{id}">' + '<div><strong class="item-title">{title}</strong></div>' + '<div><i>{description}</i></div>' + '</li>', outputTemplate = '[[{title}]]<span> </span>'; var autocomplete = new CKEDITOR.plugins.autocomplete(evt.editor, { textTestCallback: textTestCallback, dataCallback: dataCallback, itemTemplate: itemTemplate, outputTemplate: outputTemplate }); // Override default getHtmlToInsert to enable rich content output. autocomplete.getHtmlToInsert = function(item) { return this.outputTemplate.output(item); } } }, removeButtons: 'PasteFromWord' }); function textTestCallback(range) { if (!range.collapsed) { return null; } return CKEDITOR.plugins.textMatch.match(range, matchCallback); } function matchCallback(text, offset) { var pattern = /\[{2}([A-z]|\])*$/, match = text.slice(0, offset) .match(pattern); if (!match) { return null; } return { start: match.index, end: offset }; } function dataCallback(matchInfo, callback) { var data = PLACEHOLDERS.filter(function(item) { var itemName = '[[' + item.name + ']]'; return itemName.indexOf(matchInfo.query.toLowerCase()) == 0; }); callback(data); } </script> </body> </html>