execcommand

Weird behaviour with document.execCommand('insertHTML')


I'm trying to programmatically highlight all occurences of a search word by adding a CSS class like so :

const style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.innerHTML = `
.word-occurence {
  background: yellow;
  color: red;
  font-weight: bold;
  cursor: pointer;
}
`;
document.head.append(style)

document.designMode = "on";

window.getSelection().collapse(document, 0);

const word = 'Ubuntu';

while (window.find(word)) {
  document.execCommand('insertHTML', false, '<span class="word-occurence">' + window.getSelection() + '</span>');
  window.getSelection().collapseToEnd();

}
document.designMode = "off";

It works almost perfectly. When I try this on the default HTML for Apache server on Ubuntu (as can be found here : http://bl.ocks.org/SunDi3yansyah/raw/c8e7a935a9f6ee6873a2/), all the occurences of the word "Ubuntu" turned red on a yellow background but one of them (the 4th one aka the one that is at the beginning of his paragraph) got CSS inline styling instead of the class. It's missing the cursor: pointer and it has an extra font-size: 14.6667px;

I know that document.execCommand is deprecated but I'm super curious: what happened there ?


Solution

  • Found this bug easily in latest Chrome version. insertHTML command has bug with changing or even removing attributes of in-line elements such as [span]. In your case it breaks attributes for any word occurrences which are the first word of text node.

    There is no official specifications but there are plenty of info about possible bugs and ways to work around. For example, I fixed your code by replacing [span] to [em] tag following some advices from this post: Is there a way to keep execCommand("insertHTML") from removing attributes in chrome?

    Fixed part:

    document.execCommand('insertHTML', false, '<em class="word-occurence">' + window.getSelection() + '</em>');
    

    As a side effect words became italic because of tag itself, but class attribute now works perfectly - no extra font sizes and such things. Speaking of extra font size. I found trouble not only with 4th occurrence of Ubuntu which is a first word of [p] tag. Very first word near the logo which is located inside own [span] element also affected with this bug.

    In conclusion to all of this, insertHTML has various bugs while working with [span] tag.

    Here is some additional info on this topic: https://w3c.github.io/editing/docs/execCommand/#fix-disallowed-ancestors