2

I have simple javascript rich text editor consiting only of bold button that has following onclick:

  document.execCommand('bold', false)

And simple html...

<div contenteditable="true">

My problem is that when I click the bold button, text area loses it's focus, is there some solution for that?

azurinko
  • 261
  • 2
  • 11
  • 1
    well that is because the focus moves to the button.... cancel the action. If you showed your click event, I could show you a solution. – epascarello Sep 05 '17 at 14:20

2 Answers2

6

Well the focus moves to the button so you need to cancel the click action so the focus is not lost in the content editable element.

document.querySelector(".actions").addEventListener("mousedown", function (e) {
  var action = e.target.dataset.action;
  if (action) {
    document.execCommand(action, false)
    //prevent button from actually getting focused
    e.preventDefault();
  }
})
[contenteditable] {
  width: 300px;
  height: 300px;
  border: 1px solid black;
}
<div class="actions">
  <button data-action="bold">bold</button>
  <button data-action="italic">italic</button>
</div>
<div contenteditable="true"></div>
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • The text area still loses focus. – Naftali Sep 05 '17 at 14:29
  • 1
    LOL, why the downvote on a valid answer? This is what the OP wanted unlike the other answer – epascarello Sep 05 '17 at 14:29
  • 1
    @Neal, um, not when I tested it in chrome. – epascarello Sep 05 '17 at 14:29
  • I can record it if you want? ;-) – Naftali Sep 05 '17 at 14:30
  • I am in chrome (on a mac) as well. – Naftali Sep 05 '17 at 14:31
  • Well I tested it in chrome, firefox, safari and it is fine for me. If OP has issues, it can be changed to mousedown, but it should not be needed. – epascarello Sep 05 '17 at 14:33
  • Ah, it fails if you do not have a selection in the contenteditable, works fine if you have a selection for it to act upon. – epascarello Sep 05 '17 at 14:34
  • Ahh, sorry I did not test that case. Yes, fails if nothing is selected. – Naftali Sep 05 '17 at 14:34
  • Awesome! works great :-D Nice job, good eye for event change. – Naftali Sep 05 '17 at 14:35
  • @马长昆michaelbergman What in the world are you talking about? Cancelling the event keeps the contenteditable from having the focus removed so the blur is not triggered. Amazing after 3 years you are first to find issue with the solution. – epascarello Apr 08 '20 at 13:31
  • my comment is not accurate enough, i mean that press the mouse, and hold it, and drag it from the button, and release it. in common sense, the button click will not effect, but by your code, the code has run. @epascarello – defend orca Apr 09 '20 at 14:02
  • Well it is an edge case and 99% of the time what you did is not going to happen. This is the easiest solution to handle the problem. You can make it more difficult with remembering the cursor position, resetting it, and running the command, or you can do this one thing. If this answer does not work for you, that is fine. – epascarello Apr 09 '20 at 14:05
3

ANSWER UPDATE

Taking a look to this answer you can save and restore current contenteditable position adding the blur event listener to your contenteditable

An example:

//
// restore position after click
//
document.getElementById('btn').addEventListener('click', function(e) {
    restoreSelection(cpos);
})
//
// save position on blur
//
document.querySelector('div[contenteditable="true"]').addEventListener('blur', function(e) {
    cpos = saveSelection();
})



function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}
var cpos = -1;
<button id="btn">Make bold</button>
<div contenteditable="true">
    this is the text
</div>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61