Conditionally enqueue a widget’s script/stylesheet in HEAD (only when present on page!)

I’ve been trying to load scripts and styles for a WordPress widget with the following conditions…

  1. The scripts MUST load in the HEAD (else they break).
  2. The scripts must ONLY load when the widget actually displays (they’re quite heavy).

I’ve done a lot of searching, and this seems to be a common (unsolved) problem…but I’m hoping someone here has successfully implemented a workaround.

This is the best I’ve got so far…

The following is a simple widget that prints text to the sidebar. It successfully loads jQuery conditionally (when the widget is actually displayed)…though only ever in the footer! (Note: it may also only work on WordPress 3.3, though this hack may provide backwards compatibility).

class BasicWidget extends WP_Widget
{

    function __construct() {
        parent::__construct(__CLASS__, 'BasicWidget', array(
            'classname' => __CLASS__,
            'description' => "This is a basic widget template that outputs text to the sidebar"
        ));
    }

  function form($instance) {
    $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
    $title = $instance['title'];
?>
  <p><label for="<?php echo $this->get_field_id('title'); ?>">Title: <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>" /></label></p>
<?php
  }

  function update($new_instance, $old_instance) {
    $instance = $old_instance;
    $instance['title'] = $new_instance['title'];
    return $instance;
  }

  function widget($args, $instance) {

    extract($args, EXTR_SKIP);

    echo $before_widget;
    $title = empty($instance['title']) ? ' ' : apply_filters('widget_title', $instance['title']);

    if (!empty($title))
      echo $before_title . $title . $after_title;;

    echo "<h1>This is a basic widget!</h1>";

    echo $after_widget;

        // if we're echoing out content, enqueue jquery.

        if (!empty($after_widget)) {
            wp_enqueue_script('jquery');
        }
    }
}
add_action( 'widgets_init', create_function('', 'return register_widget("BasicWidget");') );

It seems once WordPress starts handling widgets, it’s too late to enqueue (or even deregister something enqueued earlier).

Any ideas would be much appreciated!

Mark.

3

WordPress as a nice function is_active_widget that you can use in your __construct and test if the widget is present in the current page and add your scripts/styles based on that ex:

function __construct() {
    parent::__construct(__CLASS__, 'BasicWidget', array(
        'classname' => __CLASS__,
        'description' => "This is a basic widget template that outputs text to the sidebar"
    ));
     if ( is_active_widget(false, false, $this->id_base) )
        add_action( 'wp_head', array(&$this, 'add_styles_and_scripts') );
}

function add_styles_and_scripts(){
    //since its wp_head you need to echo out your style link:
    echo '<link rel="stylesheet" href="http://example.com/css/style.css" type="text/css" />';
    //as for javascript it can be included using wp_enqueue_script and set the footer parameter to true:
    wp_enqueue_script( 'widget_script','http://example.com/js/script.js',array(),'',true );
}

Leave a Comment