I'm trying to implement the basic Rich Text Editing functionalities of ContentEditable in Meteor and I'm having an issue with execCommand. The undo and redo commands work fine but every other command such as bold and italic do not work and give out no errors. The code also worked fine as a regular page (I've done the obvious adaptations for Meteor such as templates and the events).
My html:
<body>
{{> buttons}}
<div id="editor" class="textZone" contenteditable="true"></div>
</body>
<template name="buttons">
<div id="rtfOptions">
<div class="separate">
<div class="rtfOption" id="undo">undo</div>
<div class="rtfOption" id="redo">redo</div>
</div>
<div class="separate">
<div class="rtfOption" id="bold">bold</div>
<div class="rtfOption" id="italic">italic</div>
</div>
</div>
</template>
My events (only 2 non-working + the undo as it works. As for the rest its pretty much the same):
if (Meteor.isClient) {
Template.buttons.events({
"click #bold": function() { // Toggles bold on/off for the selection or at the insertion point
document.execCommand("bold", false, "null");
},
"click #italic": function() { // Toggles italics on/off for the selection or at the insertion point
document.execCommand("italic", false, "null");
},
"click #undo": function() { // Undoes the last executed command.
document.execCommand('undo', false, "null");
}
)};
}
Someone know the issue? Does it have something to do with document or the scope?
If you change the div
tags to button
instead (for the clickable elements), or make the div text unselectable (e.g disabling user-select
with css) it should work as you expect.
The reason is that when you click on the div
with text inside, the execCommand
targets the div
's text (which is not contenteditable
) so the command fails silently. Try adding contenteditable="true"
to the div and you'll see that it will bold the div
's text if you click on it. Alternatively, try adding the css rule -webkit-user-select: none;
(on Chrome, vendor prefixes differ on other browsers) to disable text selection on the div, and you'll see that the execCommand
works just fine.
See a working demo here.
Code examples, for clarity:
Option 1
<template name="buttons">
<div id="rtfOptions">
<div class="separate">
<div class="rtfOption" id="bold" style="user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;">bold</div>
</div>
</div>
</template>
Option 2
<template name="buttons">
<div id="rtfOptions">
<div class="separate">
<button class="rtfOption" id="bold">bold</button>
</div>
</div>
</template>