【问题标题】:How to get rid of copy & paste text styling in ajax html editor如何摆脱 ajax html 编辑器中的复制和粘贴文本样式
【发布时间】:2011-09-01 16:30:10
【问题描述】:

我正在为新闻描述页面使用 ajax html 编辑器。当我从 word 或 internet 复制粘贴内容时,它会复制该文本、段落等的样式,这克服了 html 编辑器文本框的默认类样式,我想要的是摆脱像下面这样的内联样式,而不是 html有
我想把它保留在段落中

<span id="ContentPlaceHolder1_newsDetaildesc" class="newsDetails"><span style="font-family: arial, helvetica, sans; font-size: 11px; line-height: 14px; color: #000000; "><strong>Lorem Ipsum</strong>&nbsp;is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.<BR /> It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></span></p>

#left_column .newsDetails span[style] { font-family: Arial !important; font-size: small !important; font-weight: normal !important; color: #808080 !important; }

【问题讨论】:

  • 对不起,您是从 word 中复制文本并将其粘贴到您的网络浏览器中吗?
  • 是的,从博客中复制文本并将其粘贴到 html 编辑器
  • 您可以尝试使用 word 中的某种特殊粘贴,但我不确定我是否完全理解您的问题
  • 您是否正在寻求一种方法,您个人可以将 HTML 从 Word 粘贴到任何编辑器并获得此行为?或者您正在使用编辑器进行开发,并且您希望您的用户能够从 Word 中粘贴并获得这种行为?
  • @Muhammad Awais 另外,请向我们展示您正在寻找的输入和输出示例。

标签: asp.net html css html-editor


【解决方案1】:

首先,请注意,通过粘贴从 Word(或任何其他 HTML 源)收到的 HTML 会因源而异。即使是不同版本的 Word 也会给你完全不同的输入。如果您设计的一些代码可以完美地处理您拥有的 MS Word 版本的内容,那么它可能根本不适用于不同版本的 MS Word。

此外,一些来源会粘贴看起来像 HTML 但实际上是垃圾的内容。当您将 HTML 内容粘贴到浏览器的富文本区域时,您的浏览器与该 HTML 的生成方式无关。不要指望它在你的任何想象中都是有效的。此外,当 HTML 插入富文本区域的 DOM 时,您的浏览器会进一步处理 HTML。

因为潜在的输入变化很大,而且由于可接受的输出很难定义,所以很难为这类事情设计一个合适的过滤器。此外,您无法控制未来版本的 MS Word 将如何处理其 HTML 内容,因此您的代码将难以适应未来。

但是,振作起来!如果世界上所有的问题都是简单的问题,那将是一个非常无聊的地方。有一些潜在的解决方案。 可以保留 HTML 的好的部分并丢弃不好的部分。

看起来您的基于 HTML 的 RTE 与大多数 HTML 编辑器一样工作。具体来说,它有一个 iframe,并且在 iframe 内的文档上,它已将designMode 设置为“on”。

paste 事件发生在该 iframe 内文档的&lt;body&gt; 元素中时,您需要捕获它。我在这里非常具体,因为我必须:不要将它困在 iframe 上;不要将它困在 iframe 的窗口上;不要将它困在 iframe 的文档中。将其捕获在 iframe 内文档的 &lt;body&gt; 元素上。非常重要。

var iframe = your.rich.text.editor.getIframe(), // or whatever
    win = iframe.contentWindow,
    doc = win.document,
    body = doc.body;

// Use your favorite library to attach events. Don't actually do this
// yourself. But if you did do it yourself, this is how it would be done.
if (win.addEventListener) {
    body.addEventListener('paste', handlePaste, false);
} else {
    body.attachEvent("onpaste", handlePaste);
}

请注意,我的示例代码附加了一个名为 handlePaste 的函数。我们接下来会谈到这一点。粘贴事件很有趣:有些浏览器在粘贴之前触发它,有些浏览器在粘贴之后触发它。您需要对其进行规范化,以便您始终在粘贴后处理粘贴的内容。为此,请使用超时方法。

function handlePaste() {
    window.setTimeout(filterHTML, 50);
}

因此,在粘贴事件后 50 毫秒,将调用 filterHTML 函数。这是工作的重点:您需要过滤 HTML 并删除任何不受欢迎的样式或元素。你有很多事情要担心!

我亲眼见过MSWord粘贴在这些元素中:

  1. meta
  2. link
  3. style
  4. o:p(不同命名空间中的段落)
  5. shapetype
  6. shape
  7. 评论,如&lt;!-- comment --&gt;
  8. font
  9. 当然还有MsoNormal 类。

filterHTML 函数应该在适当的时候删除这些。您可能还希望删除您认为必要的其他项目。这是一个示例filterHTML,它删除了我上面列出的项目。

// Your favorite JavaScript library probably has these utility functions.
// Feel free to use them. I'm including them here so this example will
// be library-agnostic.
function collectionToArray(col) {
    var x, output = [];
    for (x = 0; x < col.length; x += 1) {
        output[x] = col[x];
    }
    return output;
}

// Another utility function probably covered by your favorite library.
function trimString(s) {
    return s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

function filterHTML() {
    var iframe = your.rich.text.editor.getIframe(),
        win = iframe.contentWindow,
        doc = win.document,
        invalidClass = /(?:^| )msonormal(?:$| )/gi,
        cursor, nodes = [];

    // This is a depth-first, pre-order search of the document's body.
    // While searching, we want to remove invalid elements and comments.
    // We also want to remove invalid classNames.
    // We also want to remove font elements, but preserve their contents.

    nodes = collectionToArray(doc.body.childNodes);
    while (nodes.length) {
        cursor = nodes.shift();
        switch (cursor.nodeName.toLowerCase()) {

        // Remove these invalid elements.
        case 'meta':
        case 'link':
        case 'style':
        case 'o:p':
        case 'shapetype':
        case 'shape':
        case '#comment':
            cursor.parentNode.removeChild(cursor);
            break;

        // Remove font elements but preserve their contents.
        case 'font':

            // Make sure we scan these child nodes too!
            nodes.unshift.apply(
                nodes,
                collectionToArray(cursor.childNodes)
            );

            while (cursor.lastChild) {
                if (cursor.nextSibling) {
                    cursor.parentNode.insertBefore(
                        cursor.lastChild,
                        cursor.nextSibling
                    );
                } else {
                    cursor.parentNode.appendChild(cursor.lastChild);
                }
            }

            break;

        default:
            if (cursor.nodeType === 1) {

                // Remove all inline styles
                cursor.removeAttribute('style');

                // OR: remove a specific inline style
                cursor.style.fontFamily = '';

                // Remove invalid class names.
                invalidClass.lastIndex = 0;
                if (
                    cursor.className &&
                        invalidClass.test(cursor.className)
                ) {

                    cursor.className = trimString(
                        cursor.className.replace(invalidClass, '')
                    );

                    if (cursor.className === '') {
                        cursor.removeAttribute('class');
                    }
                }

                // Also scan child nodes of this node.
                nodes.unshift.apply(
                    nodes,
                    collectionToArray(cursor.childNodes)
                );
            }
        }
    }
}

您包含了一些您想要过滤的示例 HTML,但您没有包含您希望查看的示例输出。如果您更新您的问题以显示您希望样本在过滤后的样子,我将尝试调整 filterHTML 函数以匹配。目前,请将此功能作为设计您自己的过滤器的起点。

请注意,此代码不会尝试将粘贴的内容与粘贴之前存在的内容区分开来。它不需要这样做;它删除的东西无论出现在哪里都被认为是无效的。

另一种解决方案是使用正则表达式针对文档正文的innerHTML 过滤这些样式和内容。我已经走了这条路,我建议不要这样做,而支持我在这里提出的解决方案。您将通过粘贴收到的 HTML 差异很大,以至于基于正则表达式的解析将很快遇到严重问题。


编辑:

我想我现在明白了:您正在尝试自己删除内联样式属性,对吗?如果是这样,您可以在 filterHTML 函数中通过包含以下行来执行此操作:

cursor.removeAttribute('style');

或者,您可以针对特定的内联样式进行删除,如下所示:

cursor.style.fontFamily = '';

我更新了 filterHTML 函数以显示这些行的位置。

祝你好运,编码愉快!

【讨论】:

  • 嗨,谢谢我的问题的详细解释,暂时,我没有删除粘贴的文本从复制的源继承的所有 CSS 样式,而是在我的 CSS 中使用 !important 来结束来粘贴文本的内联 css 。这看起来不像是一种正确的做法,我已经更新了上面的问题
  • 很棒的输入。从头开始构建所见即所得,并且对粘贴的项目有点格式化感到非常兴奋(然后感到恐惧)。嘘内联样式,是的,有限的正则表达式,主要是 js 删除代码汤!
【解决方案2】:

根据我从您的问题中了解到的情况,您使用的是所见即所得的编辑器。当从其他网页或 word 文档复制和粘贴文本时,您会得到一些带有内联样式等的丑陋 html。

我建议您根本不要费心解决这个问题,因为跨浏览器处理这个问题很麻烦。如果您真的想修复它,我建议您使用 TinyMCE,它可以得到您想要的这种确切行为。

您可以通过访问http://tinymce.moxiecode.com/tryit/full.php 来尝试它,只需将一些文本复制到编辑器中,然后将其全部提交以查看生成的 html。很干净。

TinyMCE 可能是 imo 中最好的 WYSIWYG 编辑器。因此,与其自己构建东西,不如使用它并根据您的确切需求对其进行自定义。

【讨论】:

    【解决方案3】:

    我总是遇到这种问题,很有趣。好吧,我的做法很简单,只需在 Windows 中打开记事本,然后将文本粘贴到记事本中,然后复制到 AJAX 文本编辑器即可。它会去掉你所有的文本样式。

    :)

    【讨论】:

    • 这个问题特别要求保持内容的结构——在从 Word 粘贴到 Web 浏览器时保持 html 标签,但删除 CSS 样式。此外,此答案不适合开发人员,而更多的是需要与最终用户交流的建议。
    【解决方案4】:

    通常,当最终用户支持 HTML 编辑时,我选择利用许多可靠的客户端 HTML 编辑控件之一,这些控件已经内置了处理此类内容的必要功能。有许多商业版本,例如来自Component Art,以及一些很棒的免费/开源版本,例如CKEditor

    所有优秀的都支持从 Word 中粘贴来去除/修复过多的 CSS。我要么只利用一个(简单的方法),要么看看他们是如何做到的(困难的)。

    【讨论】:

      【解决方案5】:

      这是一个从 HTML 中去除文本的潜在解决方案。它的工作原理是首先将文本作为 HTML 复制到一个元素中(可能应该隐藏,但在我的示例中显示以供比较)。接下来,您将获得该元素的 innerText。然后,您可以将该文本放入您喜欢的任何位置的编辑器中。您必须在编辑器上捕获粘贴事件,运行此序列以获取文本,然后将该文本放在您喜欢的编辑器中的任何位置。

      这里有一个如何做到这一点的例子:Getting text from HTML

      【讨论】:

        【解决方案6】:

        如果您使用的是 Firefox,则可以安装此扩展程序:https://addons.mozilla.org/en-US/firefox/addon/extended-copy-menu-fix-vers/。它允许您从任何网站复制文本而无需格式化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-02-29
          • 2018-10-26
          • 1970-01-01
          • 1970-01-01
          • 2015-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多