我有 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/