I'm trying to add a nonce to the inline scripts inserted in WordPress by wp_add_inline_script and wp_localize_script, but I can't figure out how to do it. It looks there are no WordPress filters for that. My goal is to have a nonce for inline scripts, so I can define a Content Security Policy that would not break common plugins that insert inline scripts. At the end the result should be something that looks like:
<script type="text/javascript" nonce="xxxxxxxxxx">....</script>
where xxxxxxxx is the nonce.
Do you have any ideas?
As the HTML for inline scripts are generated by the WordPress code
sprintf( "<script type='text/javascript'>\n%s\n</script>\n", ... )
you cannot add an attribute to the HTML script element using wp_add_inline_script() as <script type='text/javascript'> is hard coded.
However, the filter 'script_loader_tag' will allow you to change the HTML for script elements just before it is outputted by WordPress.
Note that the filter 'script_loader_tag' will not be applied to script elements added by calling wp_localize_script() since these are outputted by the WordPress code:
echo "<script type='text/javascript'>\n"; // CDATA and type='text/javascript' is not needed for HTML 5
echo "/* <![CDATA[ */\n";
echo "$output\n";
echo "/* ]]> */\n";
echo "</script>\n";
Since these are echoed and <script type='text/javascript'> is hard coded you cannot add an attribute to the HTML script elements of wp_localize_script().
Try to use wp_enqueue_scripts hook
function my_special_inline_script() {
?>
<script>
// your JS code
</script>
<?php
}
add_action( 'wp_enqueue_scripts', 'my_special_inline_script', 1, 1 );
or
function theme_prefix_enqueue_script() {
wp_add_inline_script( 'jquery', 'jQuery(document).ready(function(){});' );
}
add_action( 'wp_enqueue_scripts', 'theme_prefix_enqueue_script' );
Bit late to the party but I just faced this exact problem for the same reasons.
I solved it for wp_add_inline_script by a bit of simple str_replace action.
add_filter( 'script_loader_tag', 'add_nonce_to_script_tag', 10, 3 );
function add_nonce_to_script_tag( $tag, $handle, $src ) {
// Check the $handle and respond accordingly
if ( $handle === 'my-script' ) {
$nonce_value = wp_create_nonce('my__script__nonce'); // or ref to an existing nonce
$replace = sprintf("javascript' nonce='%s'>", $nonce_value );
$tag = str_replace( "javascript'>", $replace, $tag);
}
return $tag;
}
// Then... $data is the inline JS from wherever
wp_add_inline_script('my-script', $data, 'before');
Once the inline script loads, I am seeing the script tag output with a nonce attribute. This is working fine with my Content-Security-Policy.
Check this out
"WordPress 5.7 adds a handful of new functions that enables passing attributes, such as async or nonce"
Related
Is there a way of adding Javascript to a page directly but having Wordpress to wait for jQuery to load? Just as with using wp_enqueue_script?
In the custom page template I have the following code:
<?php if (isset($_GET['status']) && $_GET['status'] == 'newly_created') : ?>
<script>
$(function() {
App.dialogs.afterPetitionCreate();
});
</script>
<?php endif; ?>
Wordpress barks that $ is undefined. Now I do not want to load a entire .js file just to call that function. So in that sense wp_enqueue_script isn't an option. I only want to fire some JavaScript directly on the page but I do want to wait for jQuery to load.
This is what I also tried, adding the JavaScript to the footer with Wordpress:
<?php if (isset($_GET['status']) && $_GET['status'] == 'newly_created') :
add_action('wp_footer', 'my_footer_scripts');
function my_footer_scripts() { ?>
<script>
$(function () {
App.dialogs.afterPetitionCreate();
});
</script>
<?php } ?>
<?php endif; ?>
But unfortunately the same error appears $ is undefined.
So what would be the correct way to quickly load some Javascript on a custom Wordpress page template AND wait for jQuery to load?
I do not think this is a good practice.
It is better to change logic to something like this:
<?php if (isset($_GET['status']) && $_GET['status'] == 'newly_created') : ?>
<input type='hidden' id='status' name='status' value='newly_created'>
<?php endif; ?>
script.js:
$(function() {
if ( $('#status').val() === 'newly_created' ) {
App.dialogs.afterPetitionCreate()
}
});
and
wp_enqueue_script( 'afterPetitionCreate', '/path/to/script.js', array( 'jquery' ), '', true );
p.s. you can wrap wp_enqueue_script() into is_page_template( 'my-cool-page-teplate.php' ).
Have you tried running the script within the document ready event like the following code below?
<script>
jQuery(document).ready(function($){
$(function () {
App.dialogs.afterPetitionCreate();
});
});
</script>
The .ready event occurs when the object of the document or the DOM is loaded which makes it perfect to place all of your jquery events and other functions.
This is the code I ended up writing, and does exactly what I want. Like Submit Parkash mentioned, jQuery needs to be used instead of $.
/*
* Adds a single bit of Javascript to the page.
*/
function theme_embed_script($script) {
add_action('wp_footer', function ($script) {
echo '<script type="text/javascript">' . $script . '</script>';
}, 10);
do_action('wp_footer', $script);
}
Usage:
<?php theme_embed_script('jQuery(function () { alert("Hello"); });'); ?>
OR use Wordpress' wp_add_inline_script() script like David mentioned.
I use this script to filter posts from single category. I based on tags which generate also a class. It is possible to generate this script by WordPress with all tags from my site?
For example below 2 scripts (now I have 12 scripts of this type):
$(document).ready(function(){
$('tr').show();
$("#aipa").click(function(){
$("tr").show();
$('tr:not(:first)').not(".aipa").slideToggle('fast');
});
});
$(document).ready(function(){
$('tr').show();
$("#ris").click(function(){
$("tr").show();
$('tr:not(:first)').not(".ris").slideToggle('fast');
});
});
Now when I add new tags I must manually add another script:
$(document).ready(function(){
$('tr').show();
$("#next-tag").click(function(){
$("tr").show();
$('tr:not(:first)').not("#next-tag").slideToggle('fast');
});
});
Here's a way to do this. This assumes that you're using the standard blog tag system, and that your variable you're using as your ID and class is the tag's slug. Alter it as needed for your needs.
<?php $tags = get_tags(); ?>
<script>
$(document).ready(function(){
<?php foreach ( $tags as $tag ) { ?>
$('tr').show();
$("#<?php echo $tag->slug; ?>").click(function(){
$("tr").show();
$('tr:not(:first)').not(".<?php echo $tag->slug; ?>").slideToggle('fast');
});
<?php } ?>
});
</script>
This will create a single document ready function, and then generate multiple click functions.
I enqueue a bunch of scripts into the footer of my page:
function core_scripts() {
wp_deregister_script('jquery');
wp_register_script('jquery', '//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js', false, null, true);
wp_register_script('bootstrap', '//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js', array('jquery'), '3.1.1', true);
wp_register_script('flexslider', get_template_directory_uri().'/js/jquery.flexslider-min.js', array('jquery'), '2.2.2', true);
wp_register_script('jqzoom', get_template_directory_uri().'/js/jquery.jqzoom-core-pack.js', array('jquery'), '2.3', true);
wp_register_script('fancybox', get_template_directory_uri().'/js/jquery.fancybox.pack.js', array('jquery'), '2.1.5', true);
... a bunch of others ...
}
add_action('init', 'core_scripts'); // Add Custom Scripts
function write_site_scripts()
{
wp_enqueue_script('jquery');
wp_enqueue_script('bootstrap');
wp_enqueue_script('flexslider');
wp_enqueue_script('jqzoom');
wp_enqueue_script('fancybox');
...etc...
}
add_action('wp_enqueue_scripts', 'write_site_scripts'); // write all enqueued scripts
function write_custom_scripts()
{
$html = "<!-- Custom script -->
<script>
var custom = '1';
</script>";
echo $html;
}
add_action('wp_footer', 'write_custom_scripts'); // this script writes in the footer before the dependent js scripts
My problem is that the custom script is always written to the page before the jQuery scripts, I guess because the custom script is written to the page via an echo write command.
How can I add custom javascript code into the footer after the jQuery scripts have been written to the page? ie. I need to delay the add_action('wp_footer', 'write_custom_scripts'); to be executed at a later moment, or how can I use enqueue to add a custom javascript?
Note I have removed the CDN code posted earlier since this leads everyone into another discussion - a valid one, but it's not the issue I am after at this moment.
Edit II
Since the question has changed in essence many times, and In order to save you from reading ( e.g. - understanding ) all of the long explanation below, just use .
add_action('wp_footer', 'write_custom_scripts',9999);
This will set the priority to very high and will probably echo your code last ( unless you or other plugin / theme developers used a higher priority or later filter ..)
For those who want to do the right way :
function my_javascripts() {
wp_enqueue_script('the-script-handle',
'path/to/file.js',
array('jquery','other_script_that_we_depend_on'),
'scriptversion eg. 1.0',
true);
}
add_action('wp_enqueue_scripts', 'my_javascripts');
When you enqueue a script like above ( the right way ) , you can see that it wp_enqueue_script() has 4 arguments.path, dependencies ,version ,and in-footer .
This is the only right way to load a script , and if you need , just enqueue also jquery at the same function -- wp will make sure it loads first .
The dependencies means that wp will not load your script UNLESS jQuery is already loaded and will try to load jQuery FIRST ...
The LAST argument will actually define weather to load your script in the FOOTER ( TRUE ) or in header ( FALSE )
That being said , you can always load jQuery in the HEADER and not footer ( but it is not so recommended )
After that , For the last bit of your script , you can echo it in the footer , and you can also control how and when to add it .
What I do not understand , is the overall aim of your method . ( this part is about the "doing it wrong " )
Firstly - I think that loading from CDN is not a good IDEA . AND I AM NOT ALONE. it is to be considered a bad practice in WP without any meaningful Pros ( the time issue is a joke since you will be probably loading a LOT of other scripts directly AND scripts are Cached ).
While doing it - it is good that you think of a fallback, but the fallback should be wp own version - and not one that you include yourself .
If you still insist on doing it wrong , you can always do something like ( or just change order of execution ):
remove_action('wp_head', 'wp_print_scripts');
remove_action('wp_head', 'wp_print_footer_scripts', 9);
remove_action('wp_head', 'wp_enqueue_scripts', 1);
// your stuff
add_action('wp_footer', 'wp_print_scripts', 5);
add_action('wp_footer', 'wp_enqueue_scripts', 5);
add_action('wp_footer', 'wp_print_footer_scripts', 5);
Which basically allow you to echo your stuff before or after the wp_footer action at will And while technically it will work -. it is still wrong .
Edit I After question edit .
you have several problems in that code .
you are registering jQuery (CDN ) with the handle jquery which is reserved for WP.
If you want to do that ( and you shouldn´t . please don´t ) you need to deregister jquery BEFORE registering it again .
<?php wp_deregister_script( 'jquery' ); ?>
Again. I can not stress enough how wrong that is .
2 . you are registring the whole bunch of script - but where do you enqueue them ?
3 . Again . Like in comments ( I think you still do not understand )
If you have a script to add to the footer - you need to register and enqueue it with dependencies .. ( the right way )
In your case from edited question :
make a file called my_script.js
var custom = '1';
Enqueue it !
wp_enqueue_script('the-script-handle',
'path/to/my_script.js',
array('jquery','other_script_that_we_depend_on'),
'0.0.1',
true);
In this case , your script will load AFTER the dependencies you listed ...
What you are trying to do is echoing directly .
As for the comment of how to correctly pass variables - read here
And you can also do something like this ( objects ):
$data = (object) array(
'render' => 'canvas',
'size' => 100,
'radius' => ($q_corner_r * 0.3),
);
$output .=
<script type="text/javascript">;
//<![CDATA[
var options = ' . json_encode($data) . '
// ]]>;
</script>';
I have been looking for an answer for this in SOF but didn't find a clear answer
I have a plugin that forces pages to be shown when certain conditions are met. but when i try to include css files for styling i get no response .
I tried to include the file using normal html and this was a failure
then tried the wp_register_style and wp_enqueue_style as such:
function rw_add_style(){
$rw_path = plugins_url('kawaleb/style.css');
wp_register_style('testili',plugins_url('kawaleb/style.css'));
wp_enqueue_style( 'testili' );
}
add_action ('wp_enqueue_scripts','rw_add_style');
wp_enqueue_style( 'testili' );
}
I placed this code on the page that should be shown when the conditions are met
What I don't know here is how to procede after enqueing !
do I need to use html to include the stylesheet file ( and then what is the use of enqueing ?) or does it do that by itself (and then what I am missing here ? )
In the doc of codex they dont go further than telling you to register the style then enqueue it !!!
Thank you all :)
You don't need to register the style, you can just enqueue it. Also, you mentioned that you've put the code in the file where you'd like it to display, you should put it in the index file of your plugin, so in /your-plugin/index.php or whatever the main file is called, add this code:
function rw_add_style() {
wp_enqueue_style( 'testili', plugins_url( 'kawaleb/style.css' ) );
}
add_action( 'wp_enqueue_scripts', 'rw_add_style' );
If you need it only on a certain page then you should add your conditional within the function, so you could do this for example:
function rw_add_style() {
global $post;
if ( $post->post_name == 'post_name' ) {
wp_enqueue_style( 'testili', plugins_url( 'kawaleb/style.css' ) );
}
}
add_action( 'wp_enqueue_scripts', 'rw_add_style' );
And you can work out what the post name is for the page you need to enqueue it for by temporarily adding the following code to the page template:
global $post;
echo $post->post_name;
To be clear, you don't need to add any html <link> to include the CSS as you're right, there would be no point in enqueuing it then. Just add the enqueue as I described above in the main index file of your plugin and it will be automatically included in the wp_head() in your header and output just before the </head>.
I hope this helps. Good luck. =)
following the tutorial at http://josephscott.org/archives/2010/03/database-powered-css-in-wordpress-themes/ i am trying to use wordpress' parse_request function to add some php-driven CSS... mostly style options set in my theme's options panel. i am aware that my code looks a little different from the author's, but i tried it his way already. i can add the
function kia_wp_head() {
wp_enqueue_style('dynamic', get_bloginfo('stylesheet_directory') . '/admin/ . '?my-custom-content=css');
}
add_action('wp_print_styles', 'kia_wp_head');
//this shows up properly enqueued but when i click on it in source it just brings up a directory listing for the admin folder
function my_custom_wp_request( $wp ) {
if( isset($_GET['my-custom-content']) && $_GET['my-custom-content'] == 'css' ) {
# get theme options
header( 'Content-Type: text/css' ); ?>
body {
background-color: <?php echo 'red'; ?>
}
<?php
exit;
}
}
add_action( 'parse_request', 'my_custom_wp_request' );
but since the background never turns red, I am either not implementing this properly or the tutorial is missing a critical step. i've also tried the other method of putting the dynamic css in its own custom-css.php file, which is my ultimate goale, but i was just trying to see if i could interact with the parse request function properly:
function my_custom_wp_request( $wp ) {
if (
isset($_GET['my-custom-content'])
&& $_GET['my-custom-content'] == 'css'
) {
# get theme options
header( 'Content-Type: text/css' );
require dirname( __FILE__ ) . '/custom-css.php';
exit;
}
}
add_action( 'parse_request', 'my_custom_wp_request' );
here i'm not sure what dirname( FILE ) means exactly, but i have also tried using a hardcoded path and that didn't work either.
so how do i get parse_request to see my php-driven stylesheet?
/* EDIT FOR SOLUTION */
basically this doesn't work w/ wp_enqueue_style
wp_enqueue_style('dynamic', get_bloginfo('stylesheet_directory') . '/admin/ . '?my-custom-content=css');
but DOES work as described at josephscott.org by inserting the style tag directly into the head
. '/admin?my-custom-content=css">
i found that it doesn’t work w/ wp_enqueue_script. it does work as written in the tutorial by manually adding the script tag to the header.