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?
It’s not true that you have to use
wp_localize_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 widget to an array and then using
wp_localize_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.wp_enqueue_scripts
has already happened. enqueue the script directly in your widget function and output it in the footer.