title: Extracting text from a contentEditable div
body: <p>I have a div set to <code>contentEditable</code> and styled with "<code>white-space:pre</code>" so it keeps things like linebreaks. In Safari, FF and IE, the div pretty much looks and works the same. All is well. What I want to do is extract the text from this div, but in such a way that will not lose the formatting -- specifically, the line breaks.</p>
  
  <p>We are using jQuery, whose <code>text()</code> function basically does a pre-order DFS and glues together all the content in that branch of the DOM into a single lump. This loses the formatting.</p>
  
  <p>I had a look at the <code>html()</code> function, but it seems that all three browsers do different things with the actual HTML that gets generated behind the scenes in my <code>contentEditable</code> div. Assuming I type this into my div:</p>
  
  <pre><code>1
  2
  3
  </code></pre>
  
  <p>These are the results:</p>
  
  <p>Safari 4:</p>
  
  <pre><code>1
  &lt;div&gt;2&lt;/div&gt;
  &lt;div&gt;3&lt;/div&gt;
  </code></pre>
  
  <p>Firefox 3.6:</p>
  
  <pre><code>1
  &lt;br _moz_dirty=""&gt;
  2
  &lt;br _moz_dirty=""&gt;
  3
  &lt;br _moz_dirty=""&gt;
  &lt;br _moz_dirty="" type="_moz"&gt;
  </code></pre>
  
  <p>IE 8:</p>
  
  <pre><code>&lt;P&gt;1&lt;/P&gt;&lt;P&gt;2&lt;/P&gt;&lt;P&gt;3&lt;/P&gt;
  </code></pre>
  
  <p>Ugh. Nothing very consistent here. The surprising thing is that MSIE looks the most sane! (Capitalized P tag and all)</p>
  
  <p>The div will have dynamically set styling (font face, colour, size and alignment) which is done using CSS, so I'm not sure if I can use a <code>pre</code> tag (which was alluded to on some pages I found using Google).</p>
  
  <p><strong>Does anyone know of any JavaScript code and/or jQuery plugin or something that will extract text from a contentEditable div in such a way as to preserve linebreaks?</strong> I'd prefer not to reinvent a parsing wheel if I don't have to.</p>
  
  <p>Update: I cribbed the <code>getText</code> function from jQuery 1.4.2 and modified it to extract it with whitespace mostly intact (I only chnaged one line where I add a newline);</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>I call this function and use its output to assign it to an XML node with jQuery, something like:</p>
  
  <pre><code>var extractedText = extractTextWithWhitespace($(this));
  var $someXmlNode = $('&lt;someXmlNode/&gt;');
  $someXmlNode.text(extractedText);
  </code></pre>
  
  <p>The resulting XML is eventually sent to a server via an AJAX call.</p>
  
  <p>This works well in Safari and Firefox.</p>
  
  <p>On IE, only the first '\n' seems to get retained somehow. Looking into it more, it looks like jQuery is setting the text like so (line 4004 of jQuery-1.4.2.js):</p>
  
  <pre><code>return this.empty().append( (this[0] &amp;&amp; this[0].ownerDocument || document).createTextNode( text ) );
  </code></pre>
  
  <p>Reading up on <code>createTextNode</code>, it appears that IE's implementation may mash up the whitespace. Is this true or am I doing something wrong?</p>