32

我在 Chrome 中观察到一种不良行为,当一个人<p>通过删除它们之间的分隔来加入两个 's 时,就会发生这种行为。尽管<p>标签已正确连接,但 Chrome 还是将最右侧<p>标签的内容用<span>.

编辑:这发生在所有块元素上,而不仅仅是p标签。

示例

例如,当</p><p>从以下块中删除分隔符时:

<div contenteditable="true"><p>p one.</p><p>p two.</p></div>

它成为了:

<div contenteditable="true"><p>p one.<span style="font-size: 16px; line-height: 1.44;">p two.</span></p>

小提琴中的示例:Chrome 包装内容的加入<p><span>.

问题

有没有一种简单的方法可以防止 chrome 这样做?它会导致我非常想摆脱的可怕标记。

4

9 回答 9

10

有一种方法,但您需要主动设置一些样式。这个想法是告诉 Chrome 样式已经被处理好了,所以它不需要添加 SPAN 来满足样式要求。基本上,您需要将 chrome 添加的样式添加到您的 contenteditable div 下的 span 类中(参见下面的示例)。

编辑过的小提琴

以你为例:

  • 我向 contenteditable DIV 添加了一个“编辑”类
  • .edit p, span在样式中添加了一个类

这变成:

.edit {
  border: 1px solid gray;
  padding: 10px;
}
.edit p, span {
  line-height: 1.44; font-size: 16px;
}

和 DIV:

<div contenteditable="true" class="edit">...</div>

请注意,您通常不需要font-size: 16px;. 我需要添加这个,因为 fiddle 在 contenteditable 中定义了一些字体大小。在独立页面上,我不需要它。

您需要将此 Chrome“补丁”应用于它发生的任何元素(因此,如果您需要 UL、OL ......然后按照我上面的示例逻辑添加所需的内容)

于 2013-03-05T01:40:24.563 回答
6

我知道这并不是解决它的真正答案,而是一个提示如何解决它(但对 Petah 问题我将如何解决它的评论太久了)

一般来说,您会检查何时会发生此类错误。对于span创建的情况,您将侦听所有事件keydownkeypress检查键是否是退格键/删除键或插入字符的每个键(如果它是真实选择)。

如果是这种情况,那么您需要检查当前选择(插入标记的位置或实际选择),然后您就知道下一个文本元素或节点是哪个。那么您需要检查接下来的内容keypress,以及keyup是否span在插入标记之后直接创建了一个。根据浏览器错误,您需要进一步检查。如果有一个创建再次打开其内容。可以使用附加Mutation事件和辅助属性。

但我需要说我自己放弃了,转而使用 ckeditor 4。它的大部分功能我不需要,它是一个非常大的库。但是由于大量此类错误的原因,我没有看到其他解决方案。

编辑 这里更新的 js fiddle 显示了一个 Mutable 事件的想法:http: //jsfiddle.net/THPmr/6/

但这并不是万无一失的,它只是为了展示它是如何实现的(仅在 chrome 27.0.1422.0 中测试过,如果第二个文本元素包含多个文本元素,则可能不起作用p

于 2013-02-26T09:53:50.273 回答
4

这是我对删除额外跨度的看法

document.querySelector('[contenteditable=true]')
  .addEventListener('DOMNodeInserted', function(event) {
    if (event.target.tagName == 'SPAN') {
      event.target.outerHTML = event.target.innerHTML;
    }
  });
于 2016-06-04T21:49:01.460 回答
3

CSS 正在影响如何在 contenteditable 中制作标记:

div, pre { 边框:1px 纯灰色;填充:10px;行高:1.44;}

删除行高线,问题不再出现。

通常有几个与默认样式相关的 contenteditable 错误:如何避免 WebKit contentEditable 复制粘贴导致不需要的 CSS?

编辑JsFiddle 间接影响了这一点(tinkerbin 的行为不同),因为它的 CSS(normalize.css)。尝试这个:

  1. 运行你的小提琴
  2. 检查一个<p>
  3. 禁用font-sizeCSS 堆栈中的所有声明 - 包括您的 line-height
  4. 做退格
  5. 没有内联跨度

解决方案 1:使用类和 id。

不要为por声明 font-size ,div而是为p.main-content,或更简单地说,.main-content。如果 contenteditable 中元素的字体大小来自浏览器的内部默认 CSS,则 Chrome 不会添加额外的标记/内联样式。

解决方案 2:使用消毒剂。

我个人会选择#1,因为在如此通用的标签中指定字体大小和错字从来都不是一个好习惯。

于 2013-02-26T10:40:14.963 回答
3

到目前为止,我发现的最好方法是听 DOMNodeInserted 并检查 tagName。如果是跨度,您可以删除标签,但保留内容。这也使光标保持在正确的位置。

function unwrap(el, target) {
    if ( !target ) {
        target = el.parentNode;
    }
    while (el.firstChild) {
        target.appendChild(el.firstChild);
    }
    el.parentNode.removeChild(el);
}

var AutoFix = true;

document.getElementById('editable')
.addEventListener('DOMNodeInserted', function(ev) {
    if ( !AutoFix ) {
        return;
    }
    if ( ev.target.tagName=='SPAN' ) {
        unwrap(ev.target);
    }
});

我添加了一个布尔值“AutoFix”,因此您可以在需要插入跨度时禁用自动 dom 更改,因为此事件会在任何 dom 更改时触发。例如,如果您有一个允许用户插入类似 <span class="highlight">...</span> 的工具栏。

据我所知,该代码在 IE 或 FireFox 中没有副作用。

于 2014-09-03T14:56:31.143 回答
1

这也激怒了我,但我找到了一个目前运行良好的解决方案。

$('#container span').filter(function() {
    $(this).removeAttr("style");
    return $(this).html().trim().length == 0;
}).remove();

我只是从 span 元素中删除样式标签,如果它为空,则将其完全删除。您可能可以根据属性样式进行过滤,但是由于我已经在循环检查以检查以删除空跨度,因此我认为最好同时执行这两项操作。

当 chrome 第一次尝试插入为 span 继承的样式时,它确实会产生一微秒的闪烁,但您只会在删除后立即看到一次。

它并不完美,但它快速而简洁。

于 2015-02-28T22:25:32.020 回答
0

请在此处查看答案:https ://stackoverflow.com/a/24494280/2615633 要解决此问题,您可以使用此插件:jquery.chromeinsertfix

于 2014-06-30T23:06:19.873 回答
0

从某人博客上的评论中找到此链接:

(修复了最新的 WebKit 版本会产生 span 元素的错误……) https://github.com/tinymce/tinymce/commit/8e6422aefa9b6cc526a218559eaf036f1d2868cf

于 2014-04-28T07:49:55.670 回答
0

After several attempts of using provided solutions, I came up with this script:

var content = obj.textContent;
obj.innerHTML = '';
obj.textContent = content;

When someone pastes a text with html encoded chars, putting it to innerHTML results with a valid html tags, that is why I decided to purge innerHTML content before placing content into obj

于 2021-12-03T17:23:56.757 回答