0

I have created a shortcode that does some PHP processing, and then returns some javascript; current code is as follows:

<?php
add_shortcode( 'round_time_to_next_15_min_interval', 'round_time_to_next_15_min_interval' );

function round_time_to_next_15_min_interval() {

// get current date & time
$current_date = date('d-M-Y g:i:s A');
$current_time = strtotime($current_date);

// create new date & time that is the nearest next 15 minute interval
$frac = 900;
$r = $current_time % $frac;
$new_time = $current_time + ($frac-$r);
$new_date = date('d-M-Y g:i:s A', $new_time);

// JS script to localize time for user & insert result into form field
$html_out = "<script>
var date = new Date('" . $new_date . " UTC');
var NextWebinarTime = date.toLocaleString();
// document.getElementById('webinartime').innerHTML = NextWebinarTime;
document.querySelector('[value=\"Next Webinar Time:\"]').innerHTML = NextWebinarTime;
</script>
";

// return script
return $html_out;

}
?>

Currently, as expected, the shortcode spits the code out in exactly the place the shortcode is used.

What I would like to do instead is cause it to place the JS script in the footer of the page, but I can't figure out how to factor that in to my current code.

  • PS - Being as this is a single php mu-plugin file, I wasn't going to get into the challenge of creating/enqueuing a separate JS file just for this rather ad hoc purpose (I only say this to address the "you should enqueue this" remarks... which could still be valid!). Thanks – Drewdavid Sep 13 '18 at 19:35
  • It might be easier to either create a CPT for all the pages where you'll need to use this, or else use a custom postmeta field, and then enqueue the JS based off of either of those conditions. – WebElaine Sep 13 '18 at 19:45
  • Or, if you update to Gutenberg, build the form inside a custom block which enqueues the required JS on the front end. – WebElaine Sep 13 '18 at 19:46
  • Thanks @WebElaine! I realize those are good solutions... I kind of started with a shortcode and just ran with it. This could definitely be done differently. – Drewdavid Sep 13 '18 at 20:31
1

I'll address your address and thruthfully you should probably be enqueuing this, and consider using wp_add_inline_script() or wp_localize_script().

However, if you can't be bothered to do that for some reason, you can just remove the return of your shortcode, and instead use add_action('wp_footer', '…');. This is actually similar to how I enqueue registered scripts/styles only when a certain shortcode is used on pages.

You can either wrap your whole code with it if you don't need anything at the placement of the shortcode, otherwise you'll need to pass the output to the function, either by naming and passing the function or using a Closure with use(). Here's the latter version of it:

add_shortcode( 'round_time_to_next_15_min_interval', 'round_time_to_next_15_min_interval' );
function round_time_to_next_15_min_interval() {

    // get current date & time
    $current_date = date('d-M-Y g:i:s A');
    $current_time = strtotime( $current_date );

    // create new date & time that is the nearest next 15 minute interval
    $frac = 900;
    $r = $current_time % $frac;
    $new_time = $current_time + ($frac-$r);
    $new_date = date('d-M-Y g:i:s A', $new_time);

    // JS script to localize time for user & insert result into form field
    $script = "<script id='round_time_to_next_15_min_interval'>
        var date = new Date('" . $new_date . " UTC');
        var NextWebinarTime = date.toLocaleString();
        // document.getElementById('webinartime').innerHTML = NextWebinarTime;
        document.querySelector('[value=\"Next Webinar Time:\"]').innerHTML = NextWebinarTime;
    </script>
    ";

    add_action( 'wp_footer', function() use( $script ){
        echo $script;
    });

    // return script
    // return $script; // Commented Out so it doesn't output at source of the shortcode
}

I flipped the JavaScript comment around, so it outputs the innerHTML in a Div on this Example Page.

Note that if you have this shortcode on a page more than once, you'll get the script output more than once. If that's the case, you'll need to include a flag of some sort (like a global variable that starts at 0, increments to 1 after the first run, and if it's > 0, don't output the script) so that it only outputs the first time it's run - or if you instead enqueue the file, it would be a non-issue.

  • Thanks that's what I was trying to do...! Good note about multiple uses on the same page. – Drewdavid Sep 13 '18 at 20:19

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.