javascript - 切换任何标签,就像 execCommand bold 对 b 所做的那样

标签 javascript html

我有 contenteditable div,需要能够将文本包装/展开到其他标签中,例如 <code>等等。 包装它们不是问题,而是展开选定的文本,就像有 <b>hello </b><code>world</code> 时一样。我只需要打开中间的字母 (orl),似乎没有简单的方法来检测所选文本是否在 <code> 中标签或没有。所以虽然 document.execCommand("bold")使用 <b> 可以完美地完成包装/展开工作吗?和 <i>标签,有什么方法可以对除 b、i、u 之外的其他标签做同样的事情吗?

最佳答案

所以在长时间寻找解决方案但一无所获之后,我决定尝试自己编写它,所以如果有人觉得这篇文章有用,我会很高兴。 我不知道它在 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>

关于javascript - 切换任何标签,就像 execCommand bold 对 b 所做的那样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45409634/

相关文章:

html - 将 html 表单与 css 问题对齐

javascript - 为子项指定复杂的 PropType

javascript - 服务器端 JQuery 数据表结果错误

javascript - Bootstrap 3 popover 作为嵌套消息框/评论插件

javascript - PHP更改个人资料图片

html - 是否可以底部对齐图像并顶部对齐图像下方的标题?

php - 如何将表中的表单数据 POST 到 PHP

javascript - 如何在不同的车速表中显示数值

javascript - 如何将一个div的内容设置为另一个div的内容

javascript - if 语句的 Soy 模板语法