• [Moderator note: Please use the CODE button to delimit code when pasting… you guessed it… code.]

    [Josef: You should have waited: I was correcting the format. I will leave the version I corrected. See above]

    [Josef: Sorry for that, I just saw how to edit topics]

    • This topic was modified 6 years, 4 months ago by Steven Stern (sterndata).
    • This topic was modified 6 years, 4 months ago by jmeile.
    • This topic was modified 6 years, 4 months ago by jmeile.
Viewing 2 replies - 1 through 2 (of 2 total)
  • Thread Starter jmeile

    (@jmeile)

    Sorry, I didn’t see how to edit my post in order to fix the code format (Now I now :-(), so, here goes again with the proper formatting:

    I’m using wp_localize_script to inject php variables into my javascript. Currently, I created a shortcode to embed jquery ui accordions into WordPress. In order to make this understandable, I will only put the relevant parts of my code.

    The Shortcode looks like:

    
    //First accordion
    [jm-accordion-group active=2 height_style=”content”]
      [jm-accordion title=”Test1″]
        Content 1
      [/jm-accordion]
      [jm-accordion title=”Test2″]
        Content 2
      [/jm-accordion]
    [/jm-accordion-group]
    
    //Second accordion with default settings
    // for active and height_style
    [jm-accordion-group]
      [jm-accordion title=”Test3″]
        Content 4
      [/jm-accordion]
      [jm-accordion title=”Test4″]
        Content 4
      [/jm-accordion]
    [/jm-accordion-group]
    

    The idea is that I can put as many “jm-accordion-group” in my post as I want. This is so far working. This is how I’m doing it: first I enqueue the scripts:

    
    function allow_jquery_ui_accordion() {
      if ( !is_admin() ) {
        wp_enqueue_script(‘jquery-ui-accordion’);
        wp_register_script(‘jm-accordion_script’,
        get_stylesheet_directory_uri() . ‘/js/accordion.js’);
      }
    }
    add_action(‘wp_enqueue_scripts’, ‘allow_jquery_ui_accordion’);
    wp_enqueue_style(‘jquery-custom-style’,
      get_stylesheet_directory_uri().
      ’/css/jquery-ui-1.12.1/jquery-ui.css’, array(),
      ‘1’, ‘screen’
    );
    

    Here I’m basically embedding one script: ‘jquery-ui-accordion’ (From the WordPress Core). The second one is only registered since I have to send some global variable values before enqueuing it. Then I also add the style sheets from jquery-ui, which I got from their official website.

    Here my script: accordion.js, which is stored on my theme as a text file:

    
    jQuery(document).ready(function($) {
      accordion_vars.forEach(function(accordion_object) {
        $( ‘#’ + accordion_object.id ).accordion({
          active: accordion_object.active,
          heightStyle: accordion_object.height_style,
        });
      });
    })
    

    Please note the variable: accordion_object. It is an array with the attributes of each accordion. This will be injected in javascript from php by using wp_localize_script. This will be done at a later time.

    Then I define the Shortcodes and its functions

    
    add_shortcode(‘jm-accordion-group’, ‘jm_accordion_group’);
    add_shortcode(‘jm-accordion’, ‘jm_accordion’);
    

    First the main div that encapsulates all the accordion sections:

    
    function jm_accordion_group( $atts, $content = null ) {
      extract(
        shortcode_atts(array(
          ‘class’ => ”,
          ‘active’ => 1,
          ‘height_style’ => ‘content’,
        ), $atts)
      );
    
      $accordions_count = isset($GLOBALS[‘accordions_count’]) ?
        $GLOBALS[‘accordions_count’] + 1 : 1;
      $GLOBALS[‘accordions_count’] = $accordions_count;
      $id = ‘jm-accordion-‘ . $GLOBALS[‘accordions_count’];
      init_accordion($id, $active, $height_style);
      $output = ‘<div id=”‘ . $id . ‘”‘;
      if (!empty($class)) {
        $output .= ‘class=”‘ . $class . ‘”‘;
      }
      $output .= ‘>’ . do_shortcode(shortcode_unautop($content)).
        ‘</div>’;
      return $output;
    }
    

    Then each accordion section:

    
    function jm_accordion( $atts, $content = null ) {
      extract(
        shortcode_atts(array(
          ‘id’ => ”,
          ‘title’ => ‘— Untitled —‘,
          ‘tag’ => ‘h5’,
          ‘class’ => ”
        ), $atts)
      );
      $output = “<” . $tag . “>” . $title . “</” . $tag . “><div”;
      if ( !empty($id) ) {
        $output .= ‘ id=”‘ . $id . ‘”‘;
      }
      if ( !empty($class) ) {
        $output .= ‘ class=”‘ . $class . ‘”‘;
      }
      $output .= ‘>’ . do_shortcode(shortcode_unautop($content)) .
        ‘</div>’;
      return $output;
    }
    

    On the jm_accordion_group function, I’m using a global variable called accordions_count to know how many accordions were processed and based on this, an id will be generated. There you will see also a function called: init_accordion; since all accordions can be setup in a different way, ie: the ‘active’ parameter (which accordion section will be expanded by default) may not the same for the whole accordions, I’m processing all parameters and saving them into a global variable as follows:

    
    function init_accordion($id, $active, $height_style) {
      //Since the code is long, I will only put the relevant
      //parts here. After processing and converting all
      //parameters to string, I save them into a global
      //variable called: accordion_objects, which has
      //all the parameters from the accordions on a page, ie:
      //$GLOBALS[‘accordion_objects’] = [
      // {‘id’: ‘jm-accordion-1’, ‘active’: 1,
      //  ‘height_style’: ‘content’},
      // {‘id’: ‘jm-accordion-2’, ‘active’: 3,
      //  ‘height_style’: ‘auto’},
      //]
    
      //… Processing comes here
    
      //Here I stored the parameters
      if ( !isset($GLOBALS[‘accordion_objects’]) ) {
        $GLOBALS[‘accordion_objects’] = array();
      }
      $GLOBALS[‘accordion_objects’][] = array (
        ‘id’ => $id,
        ‘active’ => $active,
        ‘height_style’ => $height_style
      );
    
      //Then I enqueue the ‘jm-accordion_script’, which
      // I registered before
      wp_enqueue_script(‘jm-accordion_script’);
    
      //Finally I sent the value of the global
      //variable to javascript
      wp_localize_script(‘jm-accordion_script’, ‘accordion_vars’,
        $GLOBALS[‘accordion_objects’]);
    }
    

    So, as you see there, the ‘wp_localize_script’ call will be done each time a new accordion group is detected. This causes that the accordion_vars is embed in javascript several times, ie:

    
    <script type=’text/javascript’>
    /* <![CDATA[ */
    var accordion_vars = [{“id”:“jm-accordion-1“, “active”:“false”,
      “height_style” : “content”}];
    
    var accordion_vars = [{“id”:“jm-accordion-1”, “active”:“false”,
      “height_style” : “content”}, {“id” : “jm-accordion-2”,
      “active” : 1, “height_style” : “content”}];
    /* ]]> */
    </script>
    

    Where can I call the ‘wp_localize_script’ so that it gets called only once? I tried the ‘wp_loaded’ action, but unfortunately the value of the global is always null at that point.

    I also know that using global variables isn’t a good way, but I don’t know how else to do it.

    Thanks in advanced

    Josef

    • This reply was modified 6 years, 4 months ago by jmeile.
    • This reply was modified 6 years, 4 months ago by jmeile.
    • This reply was modified 6 years, 4 months ago by jmeile.
    Thread Starter jmeile

    (@jmeile)

    Ok, I solved this by using wp_add_inline_script instead of wp_localize_script as follows.

    First, I won’t register my accordion.js script inside of allow_jquery_ui_accordion. So, I redefined it as follows:

    
    function allow_jquery_ui_accordion() {
      if ( !is_admin() ) {
        wp_enqueue_script('jquery-ui-accordion');
      }
    }
    add_action('wp_enqueue_scripts', 'allow_jquery_ui_accordion');
    

    Then I deleted the accordion_objects global from the php code. I won’t need it after all. I only need it on the javascript. So, the new init_accordion function looks like:

    
    function init_accordion($id, $active, $height_style) {
      //... Processing comes here
      //    Some code comes here, but is not relevant to the post
      //... Finished processing. Here I will have initialized:
      //    $id, $active, and $height_style
    
      $script_data =
        "accordion_vars.push({" .
        "  'id': '$id'," .
        "  'active': $active," .
        "  'height_style' : '$height_style'" .
        "});";
    
      //If this is the first processed accordion group, then
      //the javascript variable accordion_vars is initialized
      //with an empty array
      if ($GLOBALS['accordions_count'] == 1) {
        $script_data =  "var accordion_vars = []; " . $script_data;
      }
    
      //Then I enqueue the 'jm-accordion_script'
      wp_enqueue_script(
          'jm-accordion_script',
          get_stylesheet_directory_uri() . '/js/accordion.js'
      );
    
      //Finally I add the inline javascript just before the
      //script gets excecuted
      wp_add_inline_script('jm-accordion_script', $script_data,
        'before');
    }
    

    The good thing is that even if the wp_enqueue_script function gets call several times, the script will be only embedded once. The result will look similar to this:

    
    <script type='text/javascript'’>
    var accordion_vars = []
    accordion_vars.push({
      'id': 'jm-accordion-1',
      'active': false,
      'height_style' : 'content'
    });
    accordion_vars.push({
      'id': 'jm-accordion-2',
      'active': 1,
      'height_style' : 'content'
    });
    </script>
    <script type='text/javascript'
      src='My_WordPress/themes/my_theme/js/accordion.js?ver=4.9.7'>
    </script>
    

    If somebody else has another solution, I would like to see it.

    Best regards
    Josef

    • This reply was modified 6 years, 4 months ago by jmeile.
    • This reply was modified 6 years, 4 months ago by jmeile.
    • This reply was modified 6 years, 4 months ago by jmeile.
    • This reply was modified 6 years, 4 months ago by jmeile.
Viewing 2 replies - 1 through 2 (of 2 total)
  • The topic ‘Calling wp_localize_script after the page was loaded’ is closed to new replies.