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.

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!

Similar posts

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

  • by Norm Sash on June 14, 2011 at 8:25 pm Reply

    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" 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" 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.

  • by Danny van Kooten on June 15, 2011 at 6:54 am Reply

    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. :-)

  • by Monique on June 16, 2011 at 5:23 pm Reply

    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.

    • by Danny van Kooten on June 17, 2011 at 8:11 am Reply

      Hi Monique.

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

  • by Gary on June 17, 2011 at 9:41 am Reply

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

  • by Norm Sash on June 17, 2011 at 4:05 pm Reply

    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.

    • by Danny van Kooten on June 18, 2011 at 10:59 am Reply

      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!

  • by Colleen on February 1, 2012 at 6:19 pm Reply

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

Leave a reply