0

This question already has an answer here:

For a plugin I'm creating it generates custom JavaScript that should be executed in the footer of the page. Being that it's custom JavaScript, I can't simply put it in a file and register & enqueue the file. How should I go about Registering and Enqueuing custom JavaScript?

Note: It would be for a Shortcode. The JavaScript would look something like this,

$("#CustomID").aFunction(withCustomData);

Again, I need it to be executed in the footer of the page, I can't simply return it in the shortcode.

Edit 1

The JavaScript is "truly" unique. It takes in parameters from the shortcode itself and may change depending on the time. Again, this is something that is constantly changing and something that should not be put in a file each time it needs to be loaded.

marked as duplicate by Howdy_McGee, Pieter Goosen, Mayeenul Islam, kaiser Jan 31 '16 at 13:26

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • is the script truly unique for each instance of the shortcode, or is just the data the script operates on unique? if you could give a more detailed example, then you will probably get a better answer. – Milo Jan 3 '16 at 5:21
  • @Milo Yes, the script is truly unique and it may change depending on factors for the shortcode. I tried to give more detail and edited my answer, do you have any other questions? – Tom Jan 3 '16 at 5:28
4

You can hook the wp_footer action to output arbitrary JavaScript. This the same action that WordPress uses to output footer enqueued scripts.

Here's an example that encapsulates the shortcode, data, and script output in a class:

<?php
/*
Plugin Name: WPD_Example
*/

class WPD_Example_Plugin {

    public $data = array();

    function __construct() {
        add_shortcode( 'wpd_example', array( $this, 'shortcode_func' ) );
        add_action( 'wp_footer', array( $this, 'footer_scripts' ), 9999 );
    }

    function shortcode_func( $atts ) {
        $atts = shortcode_atts( array(
            'title' => 'title'
        ), $atts, 'wpd_example' );
        $id = uniqid();
        $this->data[$id] = $atts['title'];
        wp_enqueue_script( 'jquery' );
        return '<div data-id="' . $id . '">' . $atts['title'] . '</div>';
    }

    function footer_scripts() {
        if( !empty( $this->data ) ){
            ?>
            <script type="text/javascript">
                if ( undefined !== window.jQuery ) {
                    jQuery(document).ready(function($) {
                        var myData = <?php echo wp_json_encode( $this->data ); ?>;
                        $.each( myData, function( id, title ) {
                            console.log( id + ' : ' + title );
                        });
                    });
                }
            </script>
            <?php
        }
    }

}

$wpd_plugin = new WPD_Example_Plugin;

EDIT

Here's another example that's similar to above, but enqueues a script and passes data via wp_localize_script rather than printing js directly to the page. You can access any of this data from the enqueued script in the wpdScriptData js object. Read the comments below this answer for an explanation as to why this method is safer.

<?php
/*
Plugin Name: WPD_Example
*/

class WPD_Example_Plugin {

    public $data = array();

    function __construct() {
        add_shortcode( 'wpd_example', array( $this, 'shortcode_func' ) );
        add_action( 'wp_footer', array( $this, 'footer_scripts' ), 0 );
    }

    function shortcode_func( $atts ) {
        $atts = shortcode_atts( array(
            'title' => 'title'
        ), $atts, 'wpd_example' );
        $id = uniqid();
        $this->data[$id] = $atts['title'];
        wp_enqueue_script( 'jquery' );
        wp_enqueue_script( 'wpd-script', plugins_url( '/js/script.js', __FILE__ ), array( 'jquery' ), null, true );
        return '<div data-id="' . $id . '">' . $atts['title'] . '</div>';
    }

    function footer_scripts() {
        if( !empty( $this->data ) ){
            wp_localize_script(
                'wpd-script',
                'wpdScriptData',
                $this->data
            );
        }
    }

}

$wpd_plugin = new WPD_Example_Plugin;
  • I upvoted, but IMO if you need jQuery then you need to enqueue it at the header to let it have a chance to load before the relevant code is executed. In this code it will be loaded at the footer and might not be able to load before the code is called. (unless wordpress force it to be loaded in sync, and I am not sure what it does) – Mark Kaplun Jan 3 '16 at 6:57
  • I don't like the wp_footer method. Not at less like it has been proposed in this answer. – cybmeta Jan 3 '16 at 11:26
  • @cybmeta I agree that wp_localize_script would be better, but it depends on exactly what is being passed, hence my comment asking for clarification (which I'm not entirely satisfied with). Can you outline a case where the above would fail? – Milo Jan 3 '16 at 17:27
  • For example, I can enqueue jquery in the footer, which is quite common, with wp_enqueue_script( "jquery", "..", [...], "...", true ). How to be sure taht the inline js in footer is loaded after jQuery?. Or I can use a tool for concatenation, minification and async loading before </body>, which is also quite common across the web, for example W3TC. Again, how to be sure that the inline js in footer is loaded after jQuery? Just some examples. In the linked question in my comment there are several comments (and answers) about this topic. Of course, I can be wrong..... – cybmeta Jan 3 '16 at 17:52
  • 1
    @cybmeta - I edited my answer above to include another version which enqueues and localizes a script rather than printing js directly. – Milo Jan 3 '16 at 18:46

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