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”
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.
Thanks for this solution Danny. I’ve been seeking an effective means of including inline JavaScript in Posts for awhile.
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.
I could kiss you right about now Danny! Thank you so much for this solution!
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?
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’ ?
Very interesting…how does this code snippet compare to functionality available with a plugin like Raw HTML?
Thank you very much for this, works great!
Smart!
Good luck!
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!
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.