当我在div上使用浏览器contenteditable = true以便让用户更新其中的文本时,我遇到了这个问题(使用Chrome):
当使用 delete 退格键删除换行符(跳回一行)时,浏览器会在该文本周围插入一个带内联样式集的标记。
这实在令人沮丧,因为它不仅会这样做,还会为该span标记添加内联样式,例如,如果我的字体颜色当前为黑色,则会为该span标记添加style =“color:black” 。
结果是我无法再用我的工具栏编辑该文本的颜色,因为它已通过内联样式很难设置为span标记。如果我使用删除键备份一行,也会发生同样的事情。
任何人都可以教我一两件关于满足的内容,或建议一种方法来删除跨度:s,如果它不可能阻止这种浏览器行为..
**要重现此问题** - 在浏览器中创建一个div,在其上设置内联样式,例如font-size:36px - 使用浏览器中可编辑的内容编辑div的文本,使用手动换行符写几行。 - 现在将光标放在FRONT OF / FRFORE的一段文本中并点击退格键。现在应该在光标前面的文本周围生成一个span标记,并改变它的样式。
更新 * * 所以我尝试了几种不同的解决方案,但收效甚微。首先我尝试删除所有标签,但之后我也丢失了所有的换行符(也许更好的正则表达式可以解决这个问题,我不是regExp写的专家)。
下面的所有函数首先调用keyup事件,但后来我将它们附加到取消选择文本框。如何解雇以下功能与问题无关。
//option to remove all tags
var withTags = $(textObject).html();
var withoutTags = withTags.replace(/<(?:.|\n)*?>/gm, '');
$(textObject).html(withoutTags);
我的第二次尝试更成功,删除了文本框下面的对象的样式标记(文本框内的divs跨越了chrome添加),这是我的第一个代码
//option to remove style of elements
$(textObject).children().each(function() {
$(this).removeAttr('style');
console.log('removing style from first level element: '+this);
});
然后我意识到每次编辑文本框时,chrome都可能会添加上面代码无法达到的新嵌套div / span标记级别,所以我这样做了:
//option to remove style of elements
$(textObject).children().each(function() {
$(this).removeAttr('style');
console.log('removing style from first level element: '+this);
//And of course it would be all too easy if chrome added only one level of elements...
$(this).children().each(function() {
$(this).removeAttr('style');
console.log('removing style from second level element: '+this);
});
});
但这还不够,因为嵌套的数量理论上可以是无限的。仍在努力寻找更好的解决方案。感谢任何输入=)
答案 0 :(得分:6)
实际上,问题是它不仅会插入span和p,而且如果您碰巧复制表,它会插入整个表格那里有tbody和rows 。 所以,我发现为我工作的唯一选择是:
$(document).on("DOMNodeInserted", $.proxy(function (e) {
if (e.target.parentNode.getAttribute("contenteditable") === "true") {
with (e.target.parentNode) {
replaceChild(e.target.firstChild, e.target);
normalize();
}
}
}, this));
是的,它在一定程度上影响了整个页面的性能,但它会阻止将表格和内容插入到满足的页面中。
<强>更新强>
当您希望的内容包含在一个span / p标记级别时,上面的脚本只处理基本情况。但是,如果从Word复制,则最终可能会复制整个表格。
所以,这是代码,它处理我迄今为止所抛出的所有内容:
$(document).on("DOMNodeInserted", $.proxy(function (e) {
if (e.target.parentNode.getAttribute("contenteditable") === "true") {
var newTextNode = document.createTextNode("");
function antiChrome(node) {
if (node.nodeType == 3) {
newTextNode.nodeValue += node.nodeValue.replace(/(\r\n|\n|\r)/gm, "")
}
else if (node.nodeType == 1 && node.childNodes) {
for (var i = 0; i < node.childNodes.length; ++i) {
antiChrome(node.childNodes[i]);
}
}
}
antiChrome(e.target);
e.target.parentNode.replaceChild(newTextNode, e.target);
}
}, this));
此外,您可以随意修改中间的正则表达式,以便删除在您的情况下特别危险的符号。
更新2
经过一段时间的思考和谷歌搜索,我只是将上面的代码包装成简单的jQuery插件,以简化使用。这是GitHub link
答案 1 :(得分:2)
目前,我正在使用
$(textObject).find('*').removeAttr('style');
取消选择可编辑区域。
也可以在keyup上使用。
答案 2 :(得分:2)
以下是我解决这个问题的方法
jquery remove <span> tags while preserving their contents (and replace <divs> and <p>:s with <br>)
我保留所有div,span和p标签的文本,删除这些标签,并用br替换所有div和p。我是在模糊的情况下做的,最好是在每次keydown上都这样做,但是因为我必须遍历所有这些%#¤¤%&amp; (你说的)嵌套元素。
答案 3 :(得分:1)
添加样式显示:inline-block;为了contenteditable,它不会在chrome中自动生成div,p,span
答案 4 :(得分:0)
伙计,这个问题的时机很疯狂。我正在做的事情就是强迫所有内容都在段落标签内,这是可信的div。
因此,我处理这个废话的方式是通过在每次击键时展平每个<p>
。
由于.text()
选择元素的所有文本,包括其子元素,我可以设置(在coffeescript中)
t = $(element).text()
$(element).children().remove()
$(element).text(t)
这解决了我的问题。顺便说一句,这些浏览器实现者确实非常糟糕。这里有一个很大的机会让这很容易,因为它确实是网络的未来。