0

I am using wp_localize_script to pass values to a jquery script. Sometimes this might happen several times on the same page, which means I need to set a different variable name to each wp_localize_script. That also means that my jquery script doesn't know what is the variable name being passed by wp_localize_script because the variable name is dynamically created (incremented).

So right now my solution is to add the same variable name (being passed by wp_localize_script) to a data attribute in the html tag, and then select all those attributes using a common class.

Example:

In my page I have the variable name that's going to be passed to the script dynamically generated (incremented) so that I can call wp_localize_script several times without overriding the values.

//PHP
$my_var = array('test_var'=>"yes");
wp_localize_script('my_script_handle','my_var_1',$my_var);

//Later down the page...
$my_var = array('test_var'=>"no");
wp_localize_script('my_script_handle','my_var_2',$my_var);

I also add the same variable name to a html data attribute

<div class="get_this" data-var="my_var_1">Some content</div>
<div class="get_this" data-var="my_var_2">Some more content</div>

Then in JS I use this selector:

var my_vars = $(".get_this").data("var");

my_vars.each(function()){
    alert(my_vars.test_var);
}

Is there a better approach to this? This works, but seems redundant to use wp_localize_script to send some variables over to the js script, and then have to rely on a class or data element to get all instances.

  • Why might you need to call wp_localize_script() more than once for a script? Is this because you might have multiple instances of a JavaScript 'widget' (for want of a better word), or because you have one instance, but not all data is available at once? – Stephen Harris Jun 25 '15 at 21:09
  • Correct. I Need to initialize the "widget" at different times with different data on the same page. The page is broken down into severals templates, a template may be loaded two or more times, so I need to initialize the "widget" two or more times passing different parameters each time. – gdaniel Jun 25 '15 at 21:26
0

Dynamic variable names are unpleasant to work with. A slightly better solution would be to use a single array / object which references each 'instance' using an auto-incremented integer.

This isn't a far cry from what you have already, but it keeps all you parameters inside on variable, and accessing a particular property of an object just feels nicer than dynamically creating the variable name.

The problem is, that wp_localize_script() obliterates previous calls when the object name is the same. So to ensure that you can 'collate' your parameters, you can make use of static class to store the parameters and enqueue the script as late on as possible (for the front-end wp_footer will do).

Here's a brief example:

class My_js_loader{

    private static $scripts;

    static function enqueue( $handle, $args ){
         if ( ! isset( self::$scripts[$handle] ) ) {
              self::$scripts[$handle] = array();
         }

         self::$scripts[$handle][] = $args;

         add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts' ) );

         return count( self::$scripts );
    }

    static function enqueue_scripts(){
         if ( self::$scripts ) {
              foreach( self::$scripts as $handle => $args ){
                   wp_enqueue_script( $handle );
                   wp_localize_script( $handle, $handle, $args );
              }
         }
    }

}

An example usage:

 $instance1_id = My_js_loader::enqueue( 'mywidget', array( 
     'param1' => 'foo',
     'param2' => 'bar',
 ) );
 //$instance1_id = 1;
 //generates HTML <div class="mywidget" data-mywidget-instance="1"></div>


 $instance2_id = My_js_loader::enqueue( 'mywidget', array( 
     'param1' => 'hello',
     'param2' => 'world',
 ) );
 //$instance2_id = 2;
 //generates HTML <div class="mywidget" data-mywidget-instance="2"></div>

Then in the javascript file

 $('.mywidget').each(function(){
      var inst = $(this).data('mywidget-instance');
      var args = mywidget[inst];
 });

Disadvantages

  • I'm assuming that your JavaScript handle works as a variable name. If that is not the case you can always allow a variable name to be passed to My_js_loader::enqueue() too.
  • The late loading means that it can't be dequeued easily. You could expose a dequeue method (to prevent a particular, or all current instances, from loaded). However it most cases, the corresponding mark-up has already been printed to the page, so you probably don't want it dequeued.
  • Use of static class makes testing... awkward...

Advantages

  • Avoids the situation where if your script has already been printed to the page, further calls to wp_localize_script() are ignored.
  • All parameters are contained with a nice, known and fixed variable name
  • JavaScript file always loads in the footer
  • This looks a lot more complex than what I was going for.. which is good, because I had not thought of that. Let me go through your suggestion with time and see if this is feasible for the current structure I am working with. My js is currently loaded on the footer, because they are loaded as needed in each section. Thanks. – gdaniel Jun 25 '15 at 22:36
0

I think there is a simpler way of doing this using filters. E.g

<?php
$my_var = array('test_var'=>"no");
$my_var = apply_filters('my_localize_filter',$my_var,'my_var');
wp_localize_script('my_script_handle','my_var',$my_var);
?>

And when you are going to localize again in other place in your code, just do like this:

<?php 
add_filter('my_localize_filter',function($object, $object_name){
     if($object_name=='my_var'){
          $object['test_var']='yes';
     }
     return $object;
},10,2); 
?>

This way you will be able to override or to add variables to your array

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.