Contenteditable with formatting actions

by whelkaholism

HTML

<script src="https://cdn.cfront-cloud.co.uk/scripts/koa1.2/cf.DOM.js?_cdv_=48"></script>
<div data-bind="
  contenteditable: Text, 
  contenteditableOptions: {
     actions: [ { label: 'Issue', handler: Handler } ]
}"></div>

CSS

div.cfaf-content-editable {
  background: #eeeeee;
  padding: 1em;
  min-height: 60px;
}

JavaScript

(function()
{
    function _format(range, action, options)
    {
        const els = getElsList(range.commonAncestorContainer, { startNode: range.startContainer, endNode: range.endContainer });
        console.log("els", els);

        if (action == 'clear')
        {
            els.forEach(function(n) 
            {
                n.removeAttribute('class');
                n.removeAttribute('style');
            });
            document.queryCommandSupported && document.queryCommandSupported('removeFormat') && document.execCommand('removeFormat', false, range);
        }
    }

    ko.bindingHandlers.contenteditable = {
        init:
            function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
            {
                var obs = f_valueaccessor();
                var options = allbindings.get('contenteditableOptions') || {};

                el.wrap('<div class="cfaf-content-editable-container"></div>')
                el.classList.add('cfaf-content-editable');
                el.setAttribute('contenteditable', true);

                if (options.actions)
                {
                    var toolbar = document.createElement('div');
                    toolbar.classList.add('cfaf-content-editable-toolbar');

                    options.actions.forEach(function(x)
                    {
                        var ab = document.createElement('button');
                        ab.innerText = x.label;
                        ab.addEventListener('click', function(e)
                        {
                            var sel = window.getSelection() || null;
                            var range = (sel && sel.rangeCount && sel.getRangeAt(0)) || null;

                            if (range)
                            {
                                range.setContent = function(nodename, content, css)
                                {
                                    var n =...