Reputation: 776
I'm creating a plugin for WordPress, when I use below code in plugin main file it load js in <head>
, it works fine.
wp_enqueue_script ( 'custom-script', 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-v4- rtl/4.6.0-1/js/bootstrap.bundle.min.jsf');
but when I use it inside a function (for example show_form()
):
function show_form()
{
wp_enqueue_script ( 'custom-script', 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-v4- rtl/4.6.0-1/js/bootstrap.bundle.min.js');
require_once 'form.php';
}
it loads script at the bottom of the page (before </body>
).
what's wrong with my code?
I need to enqueue script inside the <head>
only when my form.php loads.
I know I can load script directly in form.php but i need to load script via wp_enqueue_script
Upvotes: 1
Views: 6025
Reputation: 5441
You're not following best practices.
Any script should be added to the Wordpress firing sequence via wp_enqueue_scripts()
firing hook.
Fires when scripts and styles are enqueued.
Furthermore, when you take a look at the wp_enqueue_script()
function CODEX page you can see that it accept a bunch of arguments including a $in_footer
variable.
$in_footer
(
bool
) (Optional) Whether to enqueue the script before instead of in the . Defaultfalse
.
As a reminder you can also set a $deps
variable.
$deps
(
string[]
) (Optional) An array of registered script handles this script depends on. Default value:array()
.
The proper way to enqueue for example Bootstrap 4.6.0
(in your case) is to add a dependency to Jquery and load both of them in the footer, not the header. As most of the time any related js action are unnecessary before the DOM as been fully loaded. In the following example I will be enqueuing both Jquery and Bootstrap in the footer, tho you can alway change true
to false
.
As you're using a CDN you should be checking is the source is available and have a fallback locally waiting. you should also include integrity and crossorigin attributes.
add_action( 'wp_enqueue_scripts', 'plugin_scripts' );
function plugin_scripts() {
/**
* Deregister Wordpress jquery core version.
* @link https://developer.wordpress.org/reference/functions/wp_deregister_script/
*/
wp_deregister_script( 'jquery' );
/**
* Register then enqueue jquery_js (Bootstrap 4.6.x required).
* @link https://developer.wordpress.org/reference/functions/wp_register_script/
* @link https://developer.wordpress.org/reference/functions/wp_enqueue_script/
*
* Check if CDN's url is valid, if not return fallback.
* @link https://www.php.net/manual/en/function.fopen.php
*
* Add rel='preload prefetch' <link> and required attributes to bootstrap_bundle_js.
* Filters the HTML link tag of an enqueued style & add required attributes.
* @link https://developer.wordpress.org/reference/hooks/script_loader_tag/
*/
$url_jquery_js = 'https://code.jquery.com/jquery-3.5.1.slim.min.js';
$ver_jquery_js = '3.5.1-slim-min';
$tst_jquery_js = @fopen( $url_jquery_js, 'r' );
$hnd_jquery_js = 'jquery_js';
if ( $tst_jquery_js !== false )
wp_register_script( $hnd_jquery_js, $url_jquery_js, [], $ver_jquery_js, true );
else
wp_register_script( $hnd_jquery_js, trailingslashit( get_template_directory_uri() ) . 'assets/js/jquery-3.5.1.slim.min.js', [], $ver_jquery_js, true );
wp_enqueue_script( $hnd_jquery_js );
add_filter( 'script_loader_tag', 'data_jquery_js', 10, 3 );
function data_jquery_js( $tag, $handle, $src ) {
if ( $handle === 'jquery_js' ) {
$integrity = 'sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj';
$tag = str_replace(
[ "<script",
"></script>", ],
[ "<link rel='preload prefetch' href='" . esc_url( $src ) . "' as='script' integrity='" . $integrity . "' crossorigin='anonymous' />" . PHP_EOL . "<script",
"integrity='" . $integrity . "' crossorigin='anonymous'></script>", ],
$tag
);
};
return $tag;
};
/**
* Register then enqueue bootstrap_bundle_js (Bootstrap 4.6.x required).
* @link https://developer.wordpress.org/reference/functions/wp_register_script/
* @link https://developer.wordpress.org/reference/functions/wp_enqueue_script/
*
* Check if CDN's url is valid, if not return fallback.
* @link https://www.php.net/manual/en/function.fopen.php
*
* Add rel='preload prefetch' <link> and required attributes to bootstrap_bundle_js.
* Filters the HTML link tag of an enqueued style & add required attributes.
* @link https://developer.wordpress.org/reference/hooks/script_loader_tag/
*/
$url_bootstrap_bundle_js = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js';
$ver_bootstrap_bundle_js = '4.6.0';
$tst_bootstrap_bundle_js = @fopen( $url_bootstrap_bundle_js, 'r' );
$hnd_bootstrap_bundle_js = 'bootstrap_bundle_js';
if ( $tst_bootstrap_bundle_js !== false )
wp_register_script( $hnd_bootstrap_bundle_js, $url_bootstrap_bundle_js, [ 'jquery_js', ], $ver_bootstrap_bundle_js, true );
else
wp_register_script( $hnd_bootstrap_bundle_js, trailingslashit( get_template_directory_uri() ) . 'assets/js/bootstrap.bundle.min.js', [ 'jquery_js', ], $ver_bootstrap_bundle_js, true );
wp_enqueue_script( $hnd_bootstrap_bundle_js );
add_filter( 'script_loader_tag', 'data_bootstrap_bundle_js', 10, 3 );
function data_bootstrap_bundle_js( $tag, $handle, $src ) {
if ( $handle === 'bootstrap_bundle_js' ) {
$integrity = 'sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns';
$tag = str_replace(
[ "<script",
"></script>", ],
[ "<link rel='preload prefetch' href='" . esc_url( $src ) . "' as='script' integrity='" . $integrity . "' crossorigin='anonymous' />" . PHP_EOL . "<script",
"integrity='" . $integrity . "' crossorigin='anonymous'></script>", ],
$tag
);
};
return $tag;
};
};
Upvotes: 1
Reputation: 19308
When show_form()
is called, you're already too far along in the execution path to go back and insert code into the head section.
Any JS you want to load should be fired on the wp_enqueue_scripts
action. wp_enqueue_script()
can be used to determine whether code loads in the head or footer of the site.
If there are two points at which you can insert code using wp_enqueue_script()
and it's being inserted into the footer even though you haven't specified that, it's because you're calling enqueue script after the head scripts have been inserted.
You need to either determine whether a form is shown on the page earlier in the loading of the page or use your JS in a way that can be supported across the site.
Example:
function wpse_enqueue_form_scripts() {
if ( has_form() ) { // EXAMPLE... You need a way of determining this
wp_enqueue_script( 'custom-script', 'js url...');
}
}
add_action( 'wp_enqueue_scripts', 'wpse_enqueue_form_scripts' );
Upvotes: 1