Many apps (such as Slack) have a handy feature where if you type a hyphen -
and hit space on a new line, the line will automatically be transformed into a bullet (aka unordered list). How does one accomplish this functionality in TinyMCE?
I'm glad you asked! I went through a few iterations on this solution before finding one that seemed to work pretty well.
First, I defined both the trigger character for Autobullets (hyphen), and the HTML containers within which I'd like Autobullet to be triggered (in this case, paragraphs, divs, table cells, and spans):
const AUTOBULLET_TRIGGER_CHARACTER = "-";
const AUTOBULLET_VALID_CONTAINERS = [
"HTMLTableCellElement",
"HTMLParagraphElement",
"HTMLDivElement",
"HTMLElement",
];
Then, I added this event handler in the editor setup, with comments:
editor.on("KeyUp", function (e) {
var sel = editor.selection.getSel();
var caretPos = sel.anchorOffset;
var txtData = sel.anchorNode.textContent;
// Char code 160 is a non breaking space
const lineMatch = `${AUTOBULLET_TRIGGER_CHARACTER}${String.fromCharCode(
160
)}`;
if (e.key === " " && caretPos === 2 && txtData === lineMatch) {
if (
AUTOBULLET_VALID_CONTAINERS.includes(
sel.focusNode.parentElement.constructor.name
)
) {
// Create an unordered list
editor.execCommand("InsertUnorderedList", false);
// Delete the last two characters from the cursor position,
// which we know are "- " since that's what triggered the autobullet
//
// Modified from https://stackoverflow.com/a/43798749
const edRange = editor.selection.getRng();
const edNode = edRange.commonAncestorContainer;
let range = document.createRange(); // create a new range object for the deletion
range.selectNodeContents(edNode);
range.setStart(edNode, edRange.endOffset - 2); // current caret pos - 3
range.setEnd(edNode, edRange.endOffset); // current caret pos
range.deleteContents();
}
}
});
As you can see, the handler detects whether or not on keyUp
the user has triggered the character and space. Then, we insert the unordered list (critically, we use the InsertUnorderedList
command, as inserting a raw ul
and li
seems to break the list functionality) and remove the hyphen/space triggers.