我想将img
内的非contenteditable
元素替换为其文本。但是,我想保留任何img
元素,包括嵌套在其他元素中的元素。换句话说:
给出如下输入:
<div><span>Foo <strong>Bar <img src="blah.png"></strong> and more text <img src="another.png"></span> With some other text <img src="yetmore.png"></div>
我想制作:
Foo Bar <img src="blah.png"> and more text <img src="another.png"> With some other text <img src="yetmore.png">
由于这是一个contenteditable
,我不想使用innerHTML
读/写,因为它将丢失光标位置等(恢复它是硬的,因为你最终得到一个不同的DOM树,所以您的选择节点会丢失)。
我最好的选择是迭代树并手动拆分和连接文本节点等等?我希望有更好的方法,或者已经可以做这样的事情的图书馆...
答案 0 :(得分:3)
对根元素进行浅层克隆。沿着原始元素树走,收集文本。当您遇到img元素时,将收集的文本添加到作为克隆子项的文本节点。附加img。再次开始收集文本。
一直走到最后,然后用克隆替换文档中的原始根元素。
类似的东西:
function toArray(o) {
var a = [], i = o.length;
while (i--) {
a[i] = o[i];
}
return a;
}
function cleanUp(el) {
var e = el.cloneNode(false);
function addText(text) {
if (text != '') {
e.appendChild(document.createTextNode(text));
}
}
function collectText(el) {
var node, nodes = toArray(el.childNodes);
var text = '';
for (var i=0, iLen=nodes.length; i<iLen; i++) {
node = nodes[i];
if (node.tagName && node.tagName.toLowerCase() == 'img') {
addText(text);
e.appendChild(node);
text = '';
} else if (node.nodeType == 3) {
text += node.data;
} else if (node.nodeType == 1) {
addText(text);
text = '';
collectText(node);
}
}
if (text != '') {
e.appendChild(document.createTextNode(text));
}
}
collectText(el);
el.parentNode.replaceChild(e, el);
}
答案 1 :(得分:3)
进行DOM替换几乎肯定会丢失光标位置/选择,但仍然是正确的方法。我建议Rangy saving and restoring the selection和跨浏览器范围/选择处理(披露:我是Rangy的作者)。
这是一个删除非<img>
元素并在所有主流浏览器(包括IE 6)中保留先前选择/插入位置的示例。它递归地将主容器节点的<img>
和文本后代移动到DocumentFragment
,并在最终将片段附加到现在为空的容器节点之前移除所有其他节点。它还规范化(即连接相邻的文本节点)。
jsFiddle with Rangy选择保存并恢复:http://jsfiddle.net/CRLRj/1/
元素删除代码:
function removeNonImgElements(node) {
var frag = document.createDocumentFragment();
function move(node, moveSelf) {
var type = node.nodeType, name = node.nodeName;
// Deal with child nodes first
var child;
while ( (child = node.firstChild) ) {
move(child, true);
}
if (!moveSelf) {
return;
}
// Keep text, images and Rangy selection marker elements
if (type == 1 && (name == "IMG" ||
(name == "SPAN" && /^selectionBoundary/.test(node.id)))) {
frag.appendChild(node);
} else if (type == 3) {
var previousNode = frag.lastChild;
if (previousNode && previousNode.nodeType == 3) {
// Concatenate text nodes rather than have two adjacent
previousNode.data = previousNode.data + node.data;
node.parentNode.removeChild(node);
} else {
frag.appendChild(node);
}
} else {
node.parentNode.removeChild(node);
}
}
move(node, false);
node.appendChild(frag);
}
答案 2 :(得分:1)
$(document).ready(function(){
replaceChildren($('#contenteditable'));
});
function replaceChildren(elem){
$(elem).children("*").not("img").each(function(){
if ($(this).children("*").not("img").length>0){
replaceChildren(this);
}
$(this).after($(this).html());
$(this).remove();
});
}
某种递归解决方案。