Live Preview jQuery Plugin

code 0 comments suggest edit

Many web applications (such as this blog) allow users to enter HTML as a comment. For security reasons, the set of allowed tags is tightly constrained by logic running on the server. Because of this, it’s helpful to provide a preview of what the comment will look like as the user is typing the comment.

sneak peek - by ArminH on
sxc.huThat’s exactly what my live preview jQuery plugin does.

See it in action

This is the first jQuery Plugin I’ve written, so I welcome feedback. I was in the process of converting a bunch of JavaScript code in Subtext to make use of jQuery, significantly reducing the amount of hand-written code in the project. Needless to say, it was a lot of fun. I decided to take our existing live preview code and completely rewrite it using JavaScript.

All you need for the HTML is an input, typically a TEXTAREA and an element to use as the preview, typically a DIV

<textarea class="source"></textarea>

<label>Preview Area</label>
<div class="preview"></div>

And the following script demonstrates one way to hook up the preview to the textarea.

$(function() {
    $('textarea.source').livePreview({
        previewElement: $('div.preview'),
        allowedTags: ['p', 'strong', 'br', 'em', 'strike'],
        interval: 20
    });
});

One thing that’s different between this implementation and others I’ve seen is you can specify a set of allowed tags. When typing in the textbox, the preview will render any tags in that list. If the user types in tags which are not in that list, the preview will HTML encode the tags.

Keep in mind that this plugin is for previewing what comments will look like and should not be used as validation! The preview might not exactly match your server-side logic.

Also for fun, I’m hosting the source code on GitHub as a way to force myself to learn what all the fuss is about GIT.

Thanks to Bohdan Zograf, this blog post is also available in Belarusian.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

36 responses

  1. Avatar for ShakeIt
    ShakeIt December 15th, 2009

    That´s great, good job! :-)

  2. Avatar for Damon Stephenson
    Damon Stephenson December 15th, 2009


    Hello


    <br/>
    Boo
    Hello Boo

    Boo


    argh



    Seems a little buggy so far. The last boo and argh are em'd :/
    Seems quite good though!

  3. Avatar for Robby
    Robby December 15th, 2009

    Wow! That's totally sweet!

  4. Avatar for I am me
    I am me December 15th, 2009

    no WAY

  5. Avatar for Nathan
    Nathan December 15th, 2009

    Nice work! I have to say I do like jquery plugin demo pages that use the un-minified version so that I can quickly and easily copy peruse your bits.

  6. Avatar for Matthew M. Osborn
    Matthew M. Osborn December 15th, 2009

    It only works if you use lowercase ;) Just doing me job :) On the other hand this is really cool I actually had a Stackoverflow question looking for something just like this! stackoverflow.com/.../lightweight-rich-text-editor

  7. Avatar for Brian Chiasson
    Brian Chiasson December 15th, 2009

    That's a useful plugin. I did notice that if you type more text than can fit in that preview div that the preview text moves beyond the div.

  8. Avatar for haacked
    haacked December 15th, 2009

    Thanks for the feedback and bug reports. I styled the DIV to be a specific height and width. I should just change the style so it auto expands vertically.

  9. Avatar for smaclell
    smaclell December 15th, 2009

    Interesting. Are you stripping out or blocking attributes? I noticed styling still worked which I thought was kinda fun.

  10. Avatar for Pita.O
    Pita.O December 15th, 2009

    Hey Phil:
    Nice piece.
    Just found a bug, though:
    br works when you use only the non-xhtml version or the html version with separating white-space (because of the residue of plain br, really); however <br/> (ie: xhtml br without spaces) does not work

  11. Avatar for haacked
    haacked December 15th, 2009

    I pushed an update which fixes a few bugs. Pita. Newlines are automatically converted to BR tags (now that I fixed the bugs), so there's no need to type in BR tags.

  12. Avatar for farrio
    farrio December 15th, 2009

    Hoho, readlly nice.
    When did your start to play with jQuery, our MVC guy :P

  13. Avatar for Erik
    Erik December 15th, 2009

    Very nice, you should block javascript attributes (events) though.
    E.g.
    Click Me!
    Erik

  14. Avatar for Erik
    Erik December 15th, 2009

    Here's the snippet I meant for the previous comment:
    &lt;strong style="color:blue;text-decoration:underline;" onclick="alert('I am the injected script');"&gt;Click Me!&lt;/strong&gt;

  15. Avatar for Heine
    Heine December 15th, 2009

    I'd recommend stripping certain attributes as well:
    &lt;p onmouseover="javascript:alert(0)"&gt;Foobar&lt;/p&gt;
    Such attributes are very easy to exploit when &lt;img&gt; is allowed:
    &ltimg src="http://example.com/nofilehere.jpg" onerror="javascript:exploit()" /&gt;

  16. Avatar for Jhonmey
    Jhonmey December 15th, 2009

    中文

  17. Avatar for Thanigainathan
    Thanigainathan December 15th, 2009

    Hi Sir,
    Wonderful article !
    Thanks,
    Thani

  18. Avatar for Simon
    Simon December 15th, 2009

    That's really nice.
    It bears repeating that this javascript can easily be tampered with to "extend" the allowed tags, so if there was no server side validation, the usual script injection vulnerabilities could be exploited trivially.

  19. Avatar for Tomas
    Tomas December 15th, 2009

    Great job! Why don't you implement this right here in the comment field of your blog right away? =)

  20. Avatar for Ian Roke
    Ian Roke December 15th, 2009

    Nice plugin Phil but I noticed some jumping around when using the p tag on the first paragraph and also subsequent paragraphs in the preview area.
    Can this be fixed?
    Cheers, Ian.

  21. Avatar for Ira
    Ira December 15th, 2009

    I have noticed a little glitch. The allowed tag list also offers css styling. This would allow me to place things on the page where you might not want them. Take the sample from below and use it in the demo, and I get my text at the upper left of the screen.

    Hi there!



    Just a small FYI. Great plugin though!

  22. Avatar for Ira
    Ira December 15th, 2009

    Sorry, I thought the code tag would allow me to show the greater than and less thans. Here is the snip
    &lt;p style="position:absolute;top:0;left:0;&gt;Hi there!&lt;/p&gt;

  23. Avatar for Javier Lozano
    Javier Lozano December 15th, 2009

    Are you planning on providing an HtmlHelper for MVC or web control for WebForms?

  24. Avatar for RichB
    RichB December 15th, 2009

    You should be using Google's Caja JavaScript-based sanitizer to do your HTML sanitization.

  25. Avatar for Chirag
    Chirag December 15th, 2009

    This is simple solution for a very common problem. Thanks! I have seen it in action on stackoverflow.

  26. Avatar for Portman
    Portman December 15th, 2009

    Question: why did you go to the trouble of implementing a setTimeout interval to bind/unbind the keyup event? Why not just render the preview on every keyup, even if they occur more frequently than every 80ms?

  27. Avatar for Ghasem
    Ghasem December 15th, 2009

    That's really nice.

  28. Avatar for Cipher
    Cipher December 16th, 2009

    I am with Portman. Whats the point of unbinding/binding and the updatingPreview variable, since javascript is single threaded anyways?

  29. Avatar for hackee
    hackee December 16th, 2009

    There already has a lightweight but quite powerful jquery plugin doing almost the same things:
    markItUp!
    what's the diff? Haacked:)

  30. Avatar for Željko
    Željko December 16th, 2009

    strong!

  31. Avatar for tester
    tester December 16th, 2009

    FETT

  32. Avatar for Enrique
    Enrique December 16th, 2009

    Phil, when you write something on the first line and then you enter 2 ENTERs, a BR is created before the first line, on IE8, using IE8 on compatibility mode works fine.

  33. Avatar for Salman Farsi
    Salman Farsi December 17th, 2009

    Hi,
    Good Job.
    Regards

  34. Avatar for lgm
    lgm December 17th, 2009

    <br>????? phil, it's not xhtml!!!!
    your plugin should convert <br/>. actually, it doesn't :'(

  35. Avatar for Elijah Manor
    Elijah Manor December 28th, 2009

    Your plugin has made it to the
    "18 Latest jQuery Plugins for Your Next Project" http://j.mp/7VqYpx
    ;)

  36. Avatar for Benjamin &quot;balupton&quot;
    Benjamin &quot;balupton&quot; March 5th, 2010

    Got to agree with Heine, came up with the following with my own independent testing:

    asdasd


    Should really have a bold disclaimer that server side validation is still required and that it can make basic XSS exploits possible if the developer allows for the text field to have a value inserted via say a URL or saved query. As such a bad short url could make use of this, have the website insert the bad text into the textfield, and the unwary user mouses over the page, and bang their cookie details are sent away or whatnot, and some user is wondering they they just bought a bunch of stuff they didn't want.