1

I am using this code in my plugin to enqueue script:

wp_enqueue_script( 'wpfrank-ptbw-pinit-js', PTBW_PLUGIN_URL . 'assets/js/pinit.js', array('jquery'), '', true );

The wp_enqueue_script function making a default <script> tag output like this:

<script type='text/javascript' src='http://localhost/development/wp-content/plugins/pin-it-button-pinterest-widgets/assets/js/pinit.js'></script>

Want to add some extra parameter into the script tags like:

<script async defer data-pin-hover="true" src="http://localhost/development/wp-content/plugins/pin-it-button-pinterest-widgets/assets/js/pinit.js"></script>
  1. asysnc
  2. defer
  3. data-pinhover="true"

How do I achieve that using wp_enqueue_script?

Are there any hook or action to pass extra parameters?

Any help really appreciated.

5

You can use script_loader_tag filter to fulfill your requirement. add below code in your active theme's functions.php file. it will add extra parameter in your script tag.

function add_attribute_to_script_tag($tag, $handle) {
   # add script handles to the array below
   $scripts_to_defer = array('wpfrank-ptbw-pinit-js');

   foreach($scripts_to_defer as $defer_script) {
      if ($defer_script === $handle) {
         return str_replace(' src', '  async defer data-pin-hover="true" src', $tag);
      }
   }
   return $tag;
}
add_filter('script_loader_tag', 'add_attribute_to_script_tag', 10, 2);
2
  • 2
    Nice, but you could've also used in_array( $defer_script, $scripts_to_defer ) as a shortcut for the foreach () :)
    – Sally CJ
    Feb 29 '20 at 13:02
  • 2
    @SallyCJ Yes this would also work. Thanks for suggestion. :-) Feb 29 '20 at 13:12
3

I revised the answer once more because I recently noticed how the Twenty Twenty developers use the script_loader_tag hook to add async and defer to the <script> tag for the theme scripts.

  1. In twentytwenty_theme_support() in functions.php, lines #139 & #140:

    $loader = new TwentyTwenty_Script_Loader();
    add_filter( 'script_loader_tag', array( $loader, 'filter_script_loader_tag' ), 10, 2 );
    
  2. In twentytwenty_register_scripts() in functions.php, lines #208 & #209:

    wp_enqueue_script( 'twentytwenty-js', get_template_directory_uri() . '/assets/js/index.js', array(), $theme_version, false );
    wp_script_add_data( 'twentytwenty-js', 'async', true );
    
  3. And in the TwentyTwenty_Script_Loader class:

    public function filter_script_loader_tag( $tag, $handle ) {
        foreach ( [ 'async', 'defer' ] as $attr ) {
            if ( ! wp_scripts()->get_data( $handle, $attr ) ) {
                continue;
            }
            ...
        }
        return $tag;
    }
    

So what I'm trying to say/suggest, is that you should probably better off use the wp_script_add_data() to add/register the custom HTML attributes (e.g. async) for your scripts and use the wp_scripts()->get_data() to check if the <script> tag should be added with the custom HTML attributes, without having to manually specify the handle (e.g. your wpfrank-ptbw-pinit-js).

And here's an example based on the above approach, where I'm registering a list of custom or extra HTML attributes for a script using wp_script_add_data( '<handle>', 'html_attrs', [ list here ] ). Additionally, I'm using PHP's DOMDocument for a more precise result, although str_replace() or preg_replace() would also do.

add_action( 'wp_enqueue_scripts', 'my_register_scripts' );
function my_register_scripts() {
    wp_enqueue_script( 'wpfrank-ptbw-pinit-js', PTBW_PLUGIN_URL . 'assets/js/pinit.js', array( 'jquery' ), '', true );
    wp_script_add_data( 'wpfrank-ptbw-pinit-js', 'html_attrs', [
        'async'          => 'async',
        'defer'          => true,
        'data-pin-hover' => 'true',
    ] );
}

add_filter( 'script_loader_tag', 'my_filter_script_loader_tag', 10, 2 );
function my_filter_script_loader_tag( $tag, $handle ) {
    $attrs = wp_scripts()->get_data( $handle, 'html_attrs' );

    // Bail if the script doesn't have any registered custom HTML attrs.
    if ( empty( $attrs ) || ! is_array( $attrs ) ) {
        return $tag;
    }

    $dom = new DOMDocument;

    //$tag = mb_convert_encoding( $tag, 'HTML-ENTITIES', 'UTF-8' );
    $dom->loadHTML( $tag, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

    $node = $dom->getElementsByTagName( 'script' )[0];
    foreach ( $attrs as $key => $value ) {
        $node->setAttribute( $key, $value );
    }

    return $dom->saveHTML();
}
2
  • 1
    Thanks so much for the new update. Appreciated!
    – Frank
    Feb 28 '20 at 14:43
  • 1
    I made one last update... I think instead of two identical answers to the question, why not post an alternate solution, right? :)
    – Sally CJ
    Feb 29 '20 at 12:56
1

In addition of Chetan Vaghela answer, you can use a switch statement, only for performance and customization related purposes:

function add_attribute_to_script_tag($tag, $handle) {

    switch($handle){
        case 'wpfrank-ptbw-pinit-js': return str_replace(' src', ' async defer data-pin-hover="true" src', $tag);
        default: return $tag;
    }
}
add_filter('script_loader_tag', 'add_attribute_to_script_tag', 10, 2);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.