I’m trying to add a javascript bookmarklet link to a post on my WordPress site. However it isn’t coming out in the post preview. When I check the link that WordPress adds to the post it has converted it to javascript:void(0)
. This simple example reproduces the problem.
<a href="javascript:alert('Alert!');">Search Scholar</a>
There are a few other people who’ve had the same problem here, here, here, and here but no-one seems to have found a solution beyond just giving their bookmarklet code for people to copy and paste and create their own bookmarklet.
The cause of this problem is that Chrome’s XSS protection is stripping out the javascript from the link when submitting it via wp-admin. One “solution” is to add the line header("X-XSS-Protection: 0");
to wp-blog-header.php in the root folder. This is insecure as it switches off the XSS protection on your WordPress site but it does allow the bookmarklet code to be rendered when the page loads.
Are there any real solutions to this problem that don’t involve switching off XSS protection? Is there a perhaps a plugin I can install to my WordPress to allow me to add javascript:
links inside my posts?
EDIT 2 After even more research, this is actually caused by the browser’s XSS detection as mentioned by the OP (as opposed to any WordPress-specific functionality). The problem only arises when you click the
Preview
button in WordPress, and only on that initial page load. Apparently WordPress sends along some of the HTML in the request headers, and that triggers the XSS functionality in the browser. If you load the preview, and then you refresh the page, the XSS issue goes away, and thejavascript:
link is displayed as it was saved. When viewing the actual site, after publishing the page, this XSS issue is never encountered present.EDIT After some deeper research (working with @gnarf), it turns out the actual issue comes down to the way that WordPress handles
javascript:
links in its preview functionality. It would seem that WordPress has some custom Javascript that runs and converts alljavascript:
links tojavascript:void(0)
links (stripping out any custom code), but only if you’re previewing the page. After publishing the page, thejavascript:
links are rendered out properly.Original Post (describes how to stop WordPress from stripping out
javascript:
links when saving a post as a non-admin user, which is what I assumed the original problem might have been)It looks like WordPress strips out the HTML in the
content_save_pre
filter. Specifically, it calls thewp_kses_bad_protocol
method inwp-includeskses.php
:The
$allowed_protocols
parameter is retrieved via thewp_allowed_protocols()
method, which applies thekses_allowed_protocols
filter to the list of protocols.With this information, you should be able to tie into the
kses_allowed_protocols
filter to addjavascript
as a valid one (note that this, of course, would open up security issues):One way to enhance the security of this approach would be to add a check for specific users or specific roles (by default, it looks like this filter actually isn’t run on administrative accounts, so you can use
javascript:
links to your heart’s content as an admin) prior to allowing thejavascript
protocol.The initial problem is of course due to this:
To avoid installing a plugin you can use the recommended method:
Here are all the details for
wp_enqueue_script()
:http://codex.wordpress.org/Function_Reference/wp_enqueue_script
You then need to create a custom JavaScript file which you include and register with the functions you need for your posts.
You can in that file make a function which for example takes your bookmarklet link as an argument and do a
document.write
(or attaches a node to as child to a known element) to the current location.Then include the script and call the function in the post as:
you only need to link the script ones in the same post – if you use this script in every post it’s probably better to link it in the header (
header.php
template file, between the meta tags and the style sheet link).or alternatively if the above doesn’t work:
Also note that if the
src
attribute is stripped away you need to go to Users and Personal Options in dashboard to turn off the rich editor.Source and more information on how to use JavaScript in WordPress globally and in posts:
http://codex.wordpress.org/Using_Javascript#Javascript_in_Posts