Search code examples
javascriptcontenteditableexeccommand

contenteditable IE11 document.execCommand foreColor issue (works properly on Firefox)


I'm creating a simple typing tool (I have to use IE11). Note that this does not happen in Firefox, where everything works just fine.

The execCommand forecolor is giving me a undesired result:

I type some text with black, then let's say I want to type inside one of the black words but with a different color. If I place the caret in the word and click the new color I want to use (which executes document.execCommand('foreColor', false, currentForeColor);) the whole word will become of the newly selected color. If I first select the color and then place the caret in the middle of the word, the color will remain black (this also happens on Firefox).

There are a few screenshot to give an idea.

Type some black text:

type some black text

Click in the middle of the word and select a color:

click in the middle of the word and select a color

The actual desired result:

enter image description here

What I would like to achieve is that once you chose a color it will type with that color wherever you place the caret and without affecting the present words.


Solution

  • The solution to this issue was to set the color each time the user types in a character.

    event.preventDefault();
    var tmpHtml = "<font color='" + currentForeColor + "'>" + event.key + "</font>";
    pasteHtmlAtCaret(tmpHtml);
    console.log(tmpHtml);
    

    And the function I use to paste html (found here: pastHtmlAtCaret)

    function pasteHtmlAtCaret(html, selectPastedContent) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
    
            // Range.createContextualFragment() would be useful here but is
            // only relatively recently standardized and is not supported in
            // some browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            var firstNode = frag.firstChild;
            range.insertNode(frag);
    
            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                if (selectPastedContent) {
                    range.setStartBefore(firstNode);
                } else {
                    range.collapse(true);
                }
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if ( (sel = document.selection) && sel.type != "Control") {
        // IE < 9
        var originalRange = sel.createRange();
        originalRange.collapse(true);
        sel.createRange().pasteHTML(html);
        if (selectPastedContent) {
            range = sel.createRange();
            range.setEndPoint("StartToStart", originalRange);
            range.select();
        }
    }
    }
    

    Of course it's not a perfect solution, and after a certain number of elements the typing starts to get laggy.