Sha*_*rog 46 html javascript css jquery contenteditable
我有一个div设置contentEditable并用" white-space:pre" 设置样式,所以它保持像linebreaks的东西.在Safari,FF和IE中,div几乎看起来和工作原理相同.一切都很好.我想要做的是从这个div中提取文本,但是这样的方式不会丢失格式 - 特别是换行符.
我们使用的是jQuery,它的text()功能基本上是预先订购的DFS,并将DOM的那个分支中的所有内容粘合成一个整体.这会丢失格式.
我看了一下这个html()函数,但似乎所有三个浏览器都使用在我的contentEditablediv中幕后生成的实际HTML做了不同的事情.假设我在我的div中输入:
1
2
3
Run Code Online (Sandbox Code Playgroud)
这些是结果:
Safari 4:
1
<div>2</div>
<div>3</div>
Run Code Online (Sandbox Code Playgroud)
Firefox 3.6:
1
<br _moz_dirty="">
2
<br _moz_dirty="">
3
<br _moz_dirty="">
<br _moz_dirty="" type="_moz">
Run Code Online (Sandbox Code Playgroud)
IE 8:
<P>1</P><P>2</P><P>3</P>
Run Code Online (Sandbox Code Playgroud)
啊.这里没有什么非常一致的.令人惊讶的是,MSIE看起来最健康!(大写P标签和所有)
div将动态设置样式(字体,颜色,大小和对齐),这是使用CSS完成的,所以我不确定我是否可以使用pre标记(我在使用Google找到的某些页面上提到过).
有没有人知道任何JavaScript代码和/或jQuery插件或从contentEditable div中提取文本以保留换行符的方式?如果我不需要,我宁愿不重新发明解析轮.
更新:我getText从jQuery 1.4.2中抄袭了这个函数并对其进行了修改以提取它,其中大部分空格完整(我只添加了一行,我添加了换行符);
function extractTextWithWhitespace( elems ) {
var ret = "", elem;
for ( var i = 0; elems[i]; i++ ) {
elem = elems[i];
// Get the text from text nodes and CDATA nodes
if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
ret += elem.nodeValue + "\n";
// Traverse everything else, except comment nodes
} else if ( elem.nodeType !== 8 ) {
ret += extractTextWithWhitespace2( elem.childNodes );
}
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我调用此函数并使用其输出将其分配给带有jQuery的XML节点,如:
var extractedText = extractTextWithWhitespace($(this));
var $someXmlNode = $('<someXmlNode/>');
$someXmlNode.text(extractedText);
Run Code Online (Sandbox Code Playgroud)
生成的XML最终通过AJAX调用发送到服务器.
这适用于Safari和Firefox.
在IE上,只有第一个'\n'似乎以某种方式保留.再看一下,看起来jQuery正在设置文本(jQuery-1.4.2.js的第4004行):
return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
Run Code Online (Sandbox Code Playgroud)
读起来createTextNode,看来IE的实现可能会混淆空白.这是真的还是我做错了什么?
Nic*_*ver 36
不幸的是,你仍然必须为pre每个浏览器单独处理这个案例(在许多情况下我不容忍浏览器检测,使用特征检测......但在这种情况下它是必要的),但幸运的是你可以照顾他们所有非常简洁,像这样:
var ce = $("<pre />").html($("#edit").html());
if($.browser.webkit)
ce.find("div").replaceWith(function() { return "\n" + this.innerHTML; });
if($.browser.msie)
ce.find("p").replaceWith(function() { return this.innerHTML + "<br>"; });
if($.browser.mozilla || $.browser.opera ||$.browser.msie )
ce.find("br").replaceWith("\n");
var textWithWhiteSpaceIntact = ce.text();
Run Code Online (Sandbox Code Playgroud)
你可以在这里测试一下.特别是IE是一个麻烦,因为 文本转换的方式和新行,这就是为什么它得到<br>上面的处理使其一致,所以它需要2次传递才能正确处理.
在上面#edit是contentEditable组件的ID ,所以只需更改它,或使其成为一个函数,例如:
function getContentEditableText(id) {
var ce = $("<pre />").html($("#" + id).html());
if ($.browser.webkit)
ce.find("div").replaceWith(function() { return "\n" + this.innerHTML; });
if ($.browser.msie)
ce.find("p").replaceWith(function() { return this.innerHTML + "<br>"; });
if ($.browser.mozilla || $.browser.opera || $.browser.msie)
ce.find("br").replaceWith("\n");
return ce.text();
}
Run Code Online (Sandbox Code Playgroud)
你可以在这里测试一下.或者,因为这是基于jQuery方法构建的,所以将它设为插件,如下所示:
$.fn.getPreText = function () {
var ce = $("<pre />").html(this.html());
if ($.browser.webkit)
ce.find("div").replaceWith(function() { return "\n" + this.innerHTML; });
if ($.browser.msie)
ce.find("p").replaceWith(function() { return this.innerHTML + "<br>"; });
if ($.browser.mozilla || $.browser.opera || $.browser.msie)
ce.find("br").replaceWith("\n");
return ce.text();
};
Run Code Online (Sandbox Code Playgroud)
然后你就可以调用它$("#edit").getPreText(),你可以在这里测试那个版本.
直到现在,当尼科悬赏它时,我才忘记了这个问题。
我通过自己编写所需的函数、从现有 jQuery 代码库中抄袭一个函数并修改它以根据需要工作来解决这个问题。
我已经用 Safari (WebKit)、IE、Firefox 和 Opera 测试了这个功能。我没有费心检查任何其他浏览器,因为整个 contentEditable 都是非标准的。如果任何浏览器更改了实现 contentEditable 的方式,则更新也可能会破坏此功能。所以程序员要小心。
function extractTextWithWhitespace(elems)
{
var lineBreakNodeName = "BR"; // Use <br> as a default
if ($.browser.webkit)
{
lineBreakNodeName = "DIV";
}
else if ($.browser.msie)
{
lineBreakNodeName = "P";
}
else if ($.browser.mozilla)
{
lineBreakNodeName = "BR";
}
else if ($.browser.opera)
{
lineBreakNodeName = "P";
}
var extractedText = extractTextWithWhitespaceWorker(elems, lineBreakNodeName);
return extractedText;
}
// Cribbed from jQuery 1.4.2 (getText) and modified to retain whitespace
function extractTextWithWhitespaceWorker(elems, lineBreakNodeName)
{
var ret = "";
var elem;
for (var i = 0; elems[i]; i++)
{
elem = elems[i];
if (elem.nodeType === 3 // text node
|| elem.nodeType === 4) // CDATA node
{
ret += elem.nodeValue;
}
if (elem.nodeName === lineBreakNodeName)
{
ret += "\n";
}
if (elem.nodeType !== 8) // comment node
{
ret += extractTextWithWhitespace(elem.childNodes, lineBreakNodeName);
}
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)