Tuesday, February 8, 2011

jQuery/pre-wrap trick

I've had a recent encounter with Internet Explorer 7 for $DAYJOB.  For this section of code, IE7 is our minimum required browser.  I was displaying some user input and wanted to maintain the text formatting while not using <pre>, which I find ugly.  So, for a while, I was using the CSS style "white-space: pre-wrap;" which will let the text flow like html, but break at new line characters like pre.  Perfect.  This has the added benefit that the text will be editable and we have a good jQuery plugin that will take a div and turn it into a textarea and use the content of said div as the inital content.  After a while, I noticed that IE7 was not behaving.  This is because IE7 does not support the pre-wrap CSS style.  Well, that's an issue.  So after a bit of reworking, I came up with this:


$("<div/>")
  .addClass('user_input')
  .append(
    $(
      $.map(
        this.split("\n"),
        function(v, i)
        {
          return [
            $("<span/>").text(v+"\n").get(0),
            $("<br/>").get(0)
          ]
        }
      )
    )
  )

So let's break this down a little.  
  1. I create the div, and add a class to it.
  2. I begin an append of the content
  3. I then take the output from a map, and turn it into a jQuery object for the append (Yes, this is important)
  4. I use the data I've been given and split it by a new line character and use that array as the input to a jQuery map operation
  5. Please note that I used the quote form of split, not the regex form.  IE7 also removes empty array items when using the regex version.
  6. For each item from the split, I return an array.  The first is a span that includes the text we need, plus a new line, to maintain the text representation of the data.  The second is a <br/> to take place of the newline in the html
  7. Last, I return the DOM elements of the span and br.  This is important, since that's what the jQuery constructor back in step 3 expects.  Also, I must ask for element 0 since otherwise, I'll get an array instead of an element back from .get().
The best part of this whole thing, is that if I do a .text() on the div, I get exactly the text I need for the editable textarea.  Perfect!  Well, not exactly.  This may have issues with spaces being insignificant, but in our case, that's acceptable for now.

No comments:

Post a Comment