javascript - 从 contentEditable div 中提取文本

标签 javascript jquery html css contenteditable

我将一个 div 设置为 contentEditable 并设置了“white-space:pre”样式,这样它就可以保留换行符之类的东西。在 Safari、FF 和 IE 中,div 的外观和工作方式几乎相同。一切都很好。我想要做的是从此 div 中提取文本,但不会丢失格式——特别是换行符。

我们正在使用 jQuery,它的 text() 函数基本上执行预排序 DFS,并将 DOM 分支中的所有内容粘合在一起成为一个 block 。这会丢失格式。

我查看了 html() 函数,但似乎所有三种浏览器对在我的 contentEditable 中在幕后生成的实际 HTML 做了不同的事情> 分区。假设我将其输入到我的 div 中:

1
2
3

结果如下:

Safari 4:

1
<div>2</div>
<div>3</div>

火狐 3.6:

1
<br _moz_dirty="">
2
<br _moz_dirty="">
3
<br _moz_dirty="">
<br _moz_dirty="" type="_moz">

IE 8:

<P>1</P><P>2</P><P>3</P>

呃。这里没有什么非常一致的。令人惊讶的是,MSIE 看起来最理智! (大写 P 标签和所有)

div 将动态设置样式(字体、颜色、大小和对齐方式),这是使用 CSS 完成的,所以我不确定我是否可以使用 pre 标签(已被提及)在我使用 Google 发现的某些页面上)。

有谁知道任何 JavaScript 代码和/或 jQuery 插件或其他东西可以从 contentEditable div 中提取文本以保留换行符?我不想重新发明一个解析如果不需要的话,我会用轮子。

更新:我抄袭了 jQuery 1.4.2 中的 getText 函数并对其进行了修改以提取它,其中的空白大部分完好无损(我只在添加换行符的地方更改了一行);

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;
}

我调用这个函数并使用它的输出通过 jQuery 将它分配给一个 XML 节点,例如:

var extractedText = extractTextWithWhitespace($(this));
var $someXmlNode = $('<someXmlNode/>');
$someXmlNode.text(extractedText);

生成的 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 ) );

阅读 createTextNode,IE 的实现似乎混搭了空白。这是真的还是我做错了什么?

最佳答案

不幸的是,您仍然需要为 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();

You can test it out here . IE 尤其麻烦,因为它的方式是 &nbsp;和文本转换中的新行,这就是它获得 <br> 的原因上面的处理使其保持一致,因此需要 2 遍才能正确处理。

在上面#editcontentEditable 的 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();
}

You can test that here .或者,由于它无论如何都是基于 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();
};

然后你可以用$("#edit").getPreText()调用它, you can test that version here .

关于javascript - 从 contentEditable div 中提取文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3455931/

相关文章:

Javascript 全屏 api 和窗口高度

javascript - AngularJs ng-click VS jquery on ('click' )

javascript - 如何使用 jquery 对数据表进行数字排序

jquery - 输入类型按钮/提交同时进行表单验证并通过 jquery ajax 提交?

javascript - 从ngResource获取数据,然后绑定(bind)result到view

javascript - 如何将参数传递到 <span> 标记上的 jQuery.click() 函数?

javascript:检测滚动结束

javascript - 在 DIV 上设置 nowrap 时没有水平页面滚动

javascript - 这与 $(document).ready() 有什么不同?

javascript - 在 JavaScript 中使用 for..of 迭代时从数组中删除元素应该是安全的吗?