切换任何标记就像execCommand bold与b一样

时间:2017-07-31 07:19:20

标签: javascript html

我有contenteditable div,需要能够将文本打包/解包到其他标签,如<code>等等。 包装它们不是问题,而是解开所选文本,就像有<b>hello </b><code>world</code>并且我只需要打开中间的字母(orl)时,似乎没有简单的方法来检测所选文本位于<code>标记内或否。因此,虽然document.execCommand("bold")完全使用<b><i>标记完成此包装/展开作业,但除了b,i,u之外,还有其他方法可以做同样的事吗吗?

2 个答案:

答案 0 :(得分:0)

修改contenteditable div并非易事。你问的是可能的,但是这个话题太大了,并且在这里没有一些例子可以回答。

然而,之前有许多现成的库(例如CKEditor)。它们非常复杂,但也非常灵活。开箱即用,它们可能比你需要的要多得多,但是它们可以进行配置,以便您不需要的功能可以被禁用,并且它们有一个API,允许您在需要时从外部控制它们。

答案 1 :(得分:0)

因此,经过较长时间寻找解决方案并找不到任何东西,我决定尝试自己编写,所以如果有人发现这件作品有用,我会很高兴的。 我不知道它在IE或Safari上是如何执行的,并且肯定它不是最有效的方法,但是对于大多数浏览器它应该完成这项工作。

<!doctype html>
<html>
    <head>
        <title>Wrap</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script>
            function traverseParentCE(el){
                var parent = el.parentElement;
                if(!parent || (el && el.contentEditable=="true")) return el;
                while(parent && parent.contentEditable!="true"){
                    parent = parent.parentElement;
                }
                return parent;
            }
            function finishWrap(el, innHtml, marker, wrapper){
                el.innerHTML = innHtml.replace("<"+marker+">","").replace("</"+marker+">","");
                var node = el.getElementsByTagName(wrapper)[0];
                var range = document.createRange();
                range.setStart(node, 0);
                range.setEnd(node, 1);
                var sel = document.getSelection();
                sel.removeAllRanges();
                sel.addRange(range);
            }
            function wrap(tag){
                var marker = "marker";
                var wrapper = "inncnt";
                var ae = document.activeElement;
                if(ae.contentEditable!="true") return;
                var sel = document.getSelection();
                var range = sel.getRangeAt(0);
                var el = document.createElement(marker);
                el.appendChild(range.cloneContents());
                range.deleteContents();
                range.insertNode(el);
                var innHtml = el.innerHTML;
                var count = 0;
                while(true){    // I know right, this kind of replacing is horrible, but RegExp somehow didn't work for me
                    var pos = innHtml.indexOf("<"+tag+">");
                    if(pos==-1) break;
                    innHtml = innHtml.replace("<"+tag+">","").replace("</"+tag+">","");
                    count++;
                }
                innHtml.replace("<"+wrapper+">","").replace("</"+wrapper+">","");
                el.innerHTML = "<"+wrapper+">" + innHtml + "</"+wrapper+">";
                var container = traverseParentCE(range.commonAncestorContainer);
                innHtml = container.innerHTML;
                if(count>0){
                    return finishWrap(container, innHtml, marker, wrapper);
                }
                var pos = innHtml.indexOf("<"+marker+">");
                var contentBefore = innHtml.substr(0, pos);
                var lastStarting = contentBefore.indexOf("<"+tag+">");
                var lastEnding = contentBefore.indexOf("</"+tag+">");
                var wrap = false;
                if(lastStarting == -1) wrap = true;
                else if(lastStarting < lastEnding) wrap = true;
                if(wrap) innHtml = innHtml.replace(marker, tag).replace(marker, tag);
                else innHtml = innHtml.replace(marker, "/"+tag).replace("/"+marker,tag);
                var doublet = "<"+tag+"></"+tag+">";
                while(true){
                    var pos = innHtml.indexOf(doublet);
                    if(pos==-1) break;
                    innHtml = innHtml.replace(doublet, "");
                }
                return finishWrap(container, innHtml, marker, wrapper);
            }
        </script>
        <button onmousedown="wrap('b'); return false;" onmouseup="return false;" onclick="return false;">B</button>
        <button onmousedown="wrap('i'); return false;" onmouseup="return false;" onclick="return false;">I</button>
        <button onmousedown="wrap('code'); return false;" onmouseup="return false;" onclick="return false;">Code</button>
        <div style="width: 800px; height: 300px; background-color: yellow" contenteditable="true" id="out">
            Hello <b>World</b>! This <code>is some</code> sentence.
        </div>
    </body>
</html>
相关问题