Extraindo texto de um contentEditable div

Eu tenho uma div definida comocontentEditable e estilizado com "white-space:pre"para manter coisas como quebras de linha. No Safari, FF e IE, a div parece e funciona da mesma maneira. Tudo está bem. O que eu quero fazer é extrair o texto dessa div, mas de uma maneira que não perca a formatação - especificamente, as quebras de linha.

Estamos usando jQuery, cujatext() A função basicamente faz uma pré-encomenda do DFS e cola todo o conteúdo nessa ramificação do DOM em um único agrupamento. Isso perde a formatação.

Eu dei uma olhada nohtml() função, mas parece que todos os três navegadores fazem coisas diferentes com o HTML real que é gerado nos bastidores no meucontentEditable div. Supondo que eu digite isso na minha div:

1
2
3

Estes são os resultados:

Safari 4:

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

Firefox 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>

Ugh. Nada muito consistente aqui. O surpreendente é que o MSIE parece o mais sensato! (Tag P maiúsculo e tudo)

A div terá um estilo definido dinamicamente (face, cor, tamanho e alinhamento da fonte), o que é feito usando CSS. Portanto, não tenho certeza se posso usar umpre tag (mencionada em algumas páginas encontradas pelo Google).

Alguém conhece algum código JavaScript e / ou plugin jQuery ou algo que extraia texto de uma div contentEditable de maneira a preservar quebras de linha? Prefiro não reinventar uma roda de análise, se não for necessário.

Atualização: eu usei ogetText funcionou no jQuery 1.4.2 e modificou-o para extraí-lo com o espaço em branco praticamente intacto (apenas troquei uma linha onde adicionei uma nova linha);

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

Eu chamo essa função e uso sua saída para atribuí-la a um nó XML com jQuery, algo como:

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

O XML resultante é finalmente enviado para um servidor por meio de uma chamada AJAX.

Isso funciona bem no Safari e Firefox.

No IE, apenas o primeiro '\ n' parece ser mantido de alguma forma. Examinando mais, parece que o jQuery está configurando o texto da seguinte forma (linha 4004 do jQuery-1.4.2.js):

return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

Lendo sobrecreateTextNode, parece que a implementação do IE pode mascarar o espaço em branco. Isso é verdade ou estou fazendo algo errado?

questionAnswers(6)

yourAnswerToTheQuestion