首先,请注意,从Word(或任何其他HTML源代码)粘贴的HTML会因源而异。即使不同版本的Word也会给你提供完全不同的输入。如果您设计了一些完全适用于MS Word版本的内容的代码,则对于不同版本的MS Word可能完全不起作用。
此外,一些来源将粘贴看起来像HTML的内容,但实际上是垃圾。将HTML内容粘贴到浏览器的富文本区域时,浏览器与生成HTML的方式无关。不要指望它在任何想象中都是有效的。另外,当您的浏览器插入到您的富文本区域的DOM中时,您的浏览器将进一步探索HTML。
由于潜在的输入变化很大,而且由于可接受的输出很难定义,因此很难为这类事情设计合适的过滤器。此外,您无法控制未来版本的MS Word将如何处理其HTML内容,因此您的代码将难以面向未来。
但是,请记住!如果所有的世界问题都是简单的问题,那将是一个相当无聊的地方。有一些潜在的解决方案。 可以保留HTML的好的部分并丢弃不好的部分。
它看起来像您的基于HTML的RTE像大多数HTML编辑器那样工作。具体来说,它有一个iframe,并且在iframe中的文档中,它已将designMode
设置为“on”。
如果发生在该iframe中文档的<body>
元素中,您将要捕获paste
事件。我在这里非常具体,因为我必须这样做:不要将其困在iframe上;不要把它放在iframe的窗口上;不要将其记录在iframe的文档中。将其捕获到iframe中文档的<body>
元素上。很重要。
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粘贴在以下几个要素:
meta
link
style
o:p
(在不同的命名空间中的段落)
shapetype
shape
- 评论,如
<!-- comment -->
。
font
- 当然还有
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函数来显示这些行将在哪里。
好运和快乐编码!
很抱歉,您是否将文字复制并粘贴到您的网络浏览器中? – 2011-05-25 13:09:45
叶复制从博客的一个文本,并将其粘贴到HTML编辑器 – 2011-05-25 13:29:14
什么,你可以尝试是某种特殊粘贴的像字,但林不知道我完全理解你的问题 – 2011-05-25 15:07:36