Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am creating a widget plugin that a user could potentially use multiple iterations of the widget multiple times on a single widget-area / multiple widget-areas on a single page. Because of its functionality there will be differing widget-level variables that I will need to individually pass from PHP to JavaScript to take action on (via jQuery). I have used a $widget_id to wrap around the widget which works fine HTML-wise.

However I am having trouble passing the information to JavaScript -- at least when attempting to use wp_localize_script to pass info to the JavaScript file. My attempt to accomplish this was done by adding the action-hook to enqueue the JavaScript in the widget method. Unfortunately it appears that I can't even get the JavaScript to be enqueued from there, let alone am able to pass it information!

Here's what I have:

class my_widget extends WP_Widget {
   private $widget_id;
   private $variable; 
   private $plugin_location;

  function my_widget() {
    parent::WP_Widget(false, $name = 'My Widget Plugin');
    $this->plugin_location = plugin_dir_url(__FILE__);
  }

  function widget($args, $instance) {   
    $this->widget_id="widget-".time().rand(1,100).rand(1,100); //make a unique id for widget, i know there are probably better ways to do this... but this works for now...
    extract( $args );
    $this->variable = $instance['variable'];
    add_action('wp_enqueue_scripts', array( &$this, 'plugin_scripts' ));
    echo '<div id="' . $this->widget_id . '">';
    ...
    create & output widget
    ..
    echo '</div>';
   }

   ... irrelevant widget administration functions ...
  public function plugin_scripts(){
    //here we set up & pass relevant information specific to EACH INDIVIDUAL widget (can have multiple in a single widget-area) for jQuery to execute functions & methods on to the JavaScript file
    $widget_info_to_pass = array(
      "widget_id"  =>  $this->widget_id,
      "variables"  =>  $this->variables
    );

    wp_register_script( 'my-site-script'.$this->widget_id, $this->plugin_location . "js/my.js", array('jquery'),'1.2.0');
    wp_enqueue_script( 'my-site-script'.$this->widget_id );
    wp_localize_script('my-site-script'.$this->widget_id, 'php_params', $widget_id_to_pass);
  }      

}

  add_action('widgets_init', create_function('', 'return register_widget("my_widget");'));

This doesn't enqueue the script, I am fairly certain because widget doesn't fire until after wp_enqueue_scripts hook has come and gone.

Important to note: it appears that to use wp_localize_script you have to call the function before wp_head.

To that note, I tried most of the hooks and was unable to even have the script enqueue at all let alone enqueue before wp_head. If I could even get the widget method to enqueue a script I can somehow manually add embedded JavaScript defining the information for each widget instance (maybe an associative array?) - but I can't get it to enqueue any scripts at all.

Is it possible to enqueue a script from the widget method of the extended WP_Widget object or am I fighting an unwinnable battle here? Are the other ways to do this that I am missing?

------------------- UPDATE ---------------------

I updated it using your advice like such:

class my_widget extends WP_Widget {
   private $widget_id;
   private $variable; 
   private $plugin_location;

  function my_widget() {
    parent::WP_Widget(false, $name = 'My Widget Plugin');
    $this->plugin_location = plugin_dir_url(__FILE__);
  }

  function widget($args, $instance) {   
    $this->widget_id="widget-".time().rand(1,100).rand(1,100); //make a unique id for widget, i know there are probably better ways to do this... but this works for now...
    extract( $args );
    $this->variable = $instance['variable'];
   //here we set up & pass relevant information specific to EACH INDIVIDUAL widget (can have multiple in a single widget-area) for jQuery to execute functions & methods on to the javascript file
    $widget_info_to_pass = array(
      "widget_id"  =>  $this->widget_id,
      "variable"  =>  $this->variable
    );
    wp_register_script( 'my-site-script'.$this->widget_id, $this->plugin_location . "js/my.js", array('jquery'),'1.2.0');
    wp_enqueue_script( 'my-site-script'.$this->widget_id );
    wp_localize_script('my-site-script'.$this->widget_id, 'php_params', $widget_id_to_pass);
    echo '<div id="' . $this->widget_id . '">';
    ...
    create & output widget
    ..
    echo '</div>';
   }

   ... irrelevant widget administration methods ...

}

  add_action('widgets_init', create_function('', 'return register_widget("my_widget");'));

To make sure I am being passed the proper info, I made my.js contain the following:

widget_id = php_params.widget_id;
variable = php_params.variable;
console.log(widget_id + "---" + variable);

Unfortunately it only outputs to the console the FINAL widget_id and variable three times.

Any reason why this happens? Any idea how to make it output the proper iterations?

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

It's not true that you have to use wp_localise_script before the wp_head.

Since 3.3 you can use wp_enqueue_script in the body of the document (i.e. in a widget or shortcode callback) and the script is loaded in the footer.

Here's a skeleton class I've used for adding variables for each instance of a widet to an array, and then using wp_localise_script to add that entire array to the document. This loads the script, and the variables in the footer.

First register your script on the init hook.

class my_widget extends WP_Widget {

  static $variables=array();

  function my_widget() {
      //initialiser function
  }

  function widget($args, $instance) {   
     //Display widget

     //Then make sure our options will be added in the footer
     add_action('wp_footer', array(__CLASS__, 'add_options_to_script'));

     //Enqueue the script (registered on init)
     wp_enqueue_script( 'my_script');

     //Add the data to the (static) class variable `$variables`, using the widget ID.
     $id = $args['widget_id'];
     self::$variables[$id] = 'my variable for this instance'
   }

   //... irrelevant widget administration functions ...

  function add_options_to_script(){
       //If there is data to add, add it
       if(!empty(self::$widget_cal))
            wp_localize_script( 'my_script', 'my_var', self::$variables);   
  }      

}

  add_action('widgets_init', create_function('', 'return register_widget("my_widget");'));
share|improve this answer
add comment

wp_enqueue_scripts has already happened. enqueue the script directly in your widget function and output it in the footer.

share|improve this answer
    
Can you explain a bit further? (example, maybe?) thanks. –  setterGetter May 17 '12 at 16:19
    
move everything in the plugin_scripts function up to the widget function to replace where you call add_action to wp_enqueue_scripts. your javascript will be output in the footer instead of head. –  Milo May 17 '12 at 16:26
    
gracias lemme give it a go –  setterGetter May 17 '12 at 16:49
    
Milo - see my update... it 1/2 works --- it outputs to the log the information of the last generated widget 3x. –  setterGetter May 17 '12 at 17:40
    
@setterGetter - it's because php_params isn't unique. you'll have to set a unique object for each localize call. there's probably also a way you can enqueue a single script to handle all your widgets, rather than creating a dynamic script handle the way you are now. –  Milo May 17 '12 at 17:56
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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