Preserve inline JavaScript or HTML in the WP post editor

By default WordPress’ WYSIWYG editor will encode all HTML entities inside your post’s content and convert double line breaks to paragraphs. This normally means that all manually inserted HTML or JavaScript will break and if it doesn’t, it will when you switch between the ‘visual’ and ‘html’ editor in TinyMCE. Luckily, there is a small trick you can do to preserve certain parts of your post’s content just as it is.\

UPDATE (March 2013): Ben Goodyear pointed me to a post of Andy Stratton who raises a few good points on why you should not use this “raw” or “preserve” function inside your theme. Andy is right and luckily, he came up with a better solution which also looses the coupling between your content and your theme. With his plugin “Raw HTML Snippets” you can create HTML and/or JavaScript snippets which you can then easily embed inside your posts content by using a shortcode like [raw_html_snippet id="js-snippet-1"].

By adding a small hack to your theme’s functions.php file we can only call wptexturize() en wpautop() on certain parts of the content. Since there is no way to disable the TinyMCE encoding that happens when switching between ‘Visual’ and ‘HTML’ mode we need to decode the encoded HTML. Let’s say we want to add some inline JavaScript to our post. Since we need to recognize what part of the content needs to be preserved let’s wrap our inline JavaScript with a shortcode.


... post content ...

[preserve]

<script type="text/javascript">

var welcome_string = "Hello. We don't want this snippet to get messed up by wpautop() and wptexturize()";

alert(welcome_string);

</script>

[/preserve]

... some more content...

Now, inside our theme’s functions.php we’re going to remove wpautop() and wptexturize() from the_content filter and add a function of our own to the filter. This function will only call wptexturize() and wpautop() on the parts of the content that are not wrapped in our [preserve] shortcode. Most parts of this snippet come from “disable automatic formatting using a shortcode“, the only thing that has been added is the HTML decoding to revert the encoding that has been done by TinyMCE when switching modes.

function my_preserve_function($content) {
$new_content = '';
$pattern_full = '{(\[preserve\].*?\[/preserve\])}is';
$pattern_contents = '{\[preserve\](.*?)\[/preserve\]}is';
$pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE);

foreach ($pieces as $piece) {
if (preg_match($pattern_contents, $piece, $matches)) {
$new_content .= html_entity_decode($matches[1]);
} else {
$new_content .= wptexturize(wpautop($piece));
}
}

return $new_content;
}

remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wptexturize');

add_filter('the_content', 'my_preserve_function', 99);

With this snippet inside your functions.php you’ll see that you can effectively insert inline JavaScript or HTML as long as you wrap it in [preserve] and [/preserve]. When switching between Visual and HTML mode TinyMCE will still encode HTML entities but you can just ignore that cause upon generating the content everything will be decoded so that tags etc. will work just fine.

Got a better idea on how to enable inline JavaScript in your posts? Leave it in the comments!

 

15 Responses to “Preserve inline JavaScript or HTML in the WP post editor”

Norm Sash — June 14, 2011 at 8:25 pm

Hi Danny… thanks for looking at this. I’m not up on php, but I think I added the code correctly at the bottom of my theme’s functions.php file (enclosed in tags), but it doesn’t seem to make a difference.

Here is an example of code that I’m trying to get to work in a page/post. If I put it into an html widget then it works (image displays, button works), but if I past it in the html tab in tinyMCE enclosed in [preserve][/preserve] I get the result where wp strips out everything it doesn’t like.

<div class='ecwid-Product'>
<div style='text-align: center; padding-bottom: 10px;'><script type="text/javascript" src="http://app.ecwid.com/script.js?258128&quot; charset="utf-8"></script><script type="text/javascript">xProductThumbnail('productid=3631040');</script></div>
<div class='ecwid-productBrowser-head ecwid-ProductBrowser-head' style='text-align: center; padding-bottom: 15px; font: normal 20px tahoma, geneva, verdana, sans-serif'>hCG Homeopathic Oral Drops, 2 oz</div>
<div class='ecwid-productBrowser-price ecwid-ProductBrowser-price' style='text-align: center; padding-bottom: 15px' id='ecwid-price-3631040'>$50.00</div>
<table align='center' border='0'><tr><td align='left' class='ecwid'></td></tr></table><div style='text-align: center'><script type="text/javascript" src="http://app.ecwid.com/script.js?258128&quot; charset="utf-8"></script><script type="text/javascript">xAddToBag('productid=3631040');</script></div>
</div>

Should result in a image of a bottle and a cart button.

Danny van Kooten — June 15, 2011 at 6:54 am

Works fine for me, make sure you’ll paste your snippet when in ‘HTML’ mode cause TinyMCE will try to add hyperlinks to the script’s source etc. when you paste something in Visual mode. You can switch back to Visual mode after pasting though, some encoding will occur but nothing bad.

When you still can’t get it to work, drop me a line trough my contact form with the URL of the page you’r trying to add it on so I can have a look on what the output is. :-)

Monique — June 16, 2011 at 5:23 pm

Isn’t there a method to use widgets as posts? In my theme e.g. you can choose for pages with only one row. On such page I would like to put one big form of your newsletter-signup plugin in the middle of my page. All traffic going through certain adds would then pass through the signup form because most of the real information is for subscribers only and happens by newsletter.

    Danny van Kooten — June 17, 2011 at 8:11 am

    Hi Monique.

    You can use the shortcode [newsletter-sign-up-form] to show a newsletter sign-up form in your posts or pages. :-)

Gary — June 17, 2011 at 9:41 am

Thanks for this solution Danny. I’ve been seeking an effective means of including inline JavaScript in Posts for awhile.

Norm Sash — June 17, 2011 at 4:05 pm

Thanks for looking at the trouble I’m having with this, Danny. I sent you an email with some login information in case you get some time to investigate further.

    Danny van Kooten — June 18, 2011 at 10:59 am

    Hi Norm,

    I just took a look and figured it out. TinyMCE automatically turns the src attributes into links when pasting script tags in Visual mode. When unlinking these links it leaves a " at the end of the src attribute, which should be it’s decoded equivalent: “.

    Hope that helps you, and others experiencing the same!

Colleen — February 1, 2012 at 6:19 pm

I could kiss you right about now Danny! Thank you so much for this solution!

kamlesh — February 17, 2012 at 9:23 am

hi Danny

i am trying to call tiny mce Editor inside my plugin function and i tried to call this function with ajax and editor not working properly.

I am getting this error (switchEditors is not defined). but when i tried to call same function without ajax it’s working fine.

can you help me please?

Ankur — February 29, 2012 at 10:23 am

Hey Danny,
this worked perfectly but only the super admin can create posts with tags using this..
can i get the same functionality for the ‘editors,subscribers’ ?

Aminka Ozmun — April 15, 2012 at 1:46 am

Very interesting…how does this code snippet compare to functionality available with a plugin like Raw HTML?

zone — May 8, 2012 at 1:18 pm

Thank you very much for this, works great!
Smart!
Good luck!

Ben Goodyear — February 11, 2013 at 8:51 pm

Hi,

Thanks for the information, although this is actually a bad way to go about it. I’d suggest reading the following right up of why:

http://theandystratton.com/2011/shortcode-autoformatting-html-with-paragraphs-and-line-breaks

And then go ahead and use the Raw HTML Snippets plugin which the above author made, works perfectly and breaks nothing.

Cheers!

    Danny van Kooten — March 10, 2013 at 12:50 pm

    Hey Ben, A tad late but as I’m travelling at the moment late is better than never. I’ve read the article and you (and Andy) are totally right – I’ve thus updated the post with a link to his post and the plugin you mentioned. Great catch, thanks!

Leave a Reply

Pallet Tafels