Month: February 2017

Hooking into the onclick event of buttons in Divi

In the Divi Theme Users & Elegant Marketplace group, Brett Bumeter asked, “anyone ever find a quick way to add an onclick event to a Divi Button?”

More specifically, Brett needs to replicate the onclick event on a regular html button, but using a Divi button.

<button onclick="myFunction()">Click me</button>

First thing we need to do is look at a Divi button’s html.

<a class="et_pb_button  et_pb_button_0 et_pb_module et_pb_bg_layout_light" href="">Button</a>

So a Divi button is really just a styled anchor tag. That’s fine, we can use the onclick event on an anchor tag. However we can’t edit a Divi button’s html, so we can’t add a function to the onclick event. What we can do is use some jQuery to bind a function to the anchors onclick event.

Here’s what that would look like:

$(".et_pb_button").on("click", function(){
    event.preventDefault();
    alert("Button clicked"); 
 });

So what this does is bind to the onclick event of any element that has a class of “et_pb_button”, prevent the default action of that element (in this case opening a url) and then performs whatever functionality you need (in this case showing the alert).

Pretty simple really. You can use this Javascript snippet in a child theme as is, or you can insert it into the Divi Theme Options -> Integrations -> Add code to the < head > of your blog’ area. If you are going to go the second route, you will need to wrap the snippet above in a document ready enclosure and some script tags, like so

<script>
jQuery(function ($) {
    $( document ).ready(function() {
        $(".et_pb_button").on("click", function(){
            event.preventDefault();
            alert("Button clicked"); 
        });
    }); 
});
</script>

You could also take this a step further, and use it to pass some data to the onclick event, by using a custom button id or class. Let’s say we give the button a custom id of ‘one’.

$(".et_pb_button").on("click", function(){
    var id = $(this).attr("id");
    alert("Button " + id + " clicked");
});

In this instance the custom id of ‘one’ would be passed to the ‘id’ variable, which could then be used to call some other function, which needs that value.

Happy Diviing.

Filed under: Development, Divi, WordPressTagged with: , ,

Using anchor links to open accordions and tabs in Divi – from another page!

The most popular article on my blog so far (by way of comments on it) is the one on Using anchor links to open accordions and tabs in Divi. It’s so popular that when the demo page broke recently I even had a few people comment to ask if the process still worked with newer versions of Divi (it does, by the way).

It being the most popular article, the most popular question I get about it is “How do I link to and open an accordion or tab, from an external page?”. Well, today I share that solution.

Before we begin – This article is going to be a little more advanced than my usual Divi posts. This is because it is going to require delving into the world of PHP and WordPress action hooks. For the purposes of this article I am not going to delve too deeply into those topics, so I do suggest reading the relevant documentation on WordPress.org. Also, for the purposes of this article, you are going to need to know how to include PHP into your WordPress site (either via a Divi child theme or a plugin). If you are new to PHP I recommend reading my Child Theme series, especially the article on Making child themes part of your development best practice. For this article, we’ll use a child theme, because it’s the easiest way.

Ok, all caught up? Good, let’s begin!

Preparation: Understand Query Strings

The first thing you need to understand is query strings. Query strings are not something you see a lot of lately (as pretty permalinks are the norm) but they are what existed before permalinks were made popular. Query strings look something like this:

 http://mycooldomain.com/?post_name=my-cool-article 

See how I am specifying that post_name is equal to my-cool-article after the question mark sign? This is a query string. In this string I am passing the variable post_name and giving it a value of my-cool-article. Once the url before the query string loads (in this case just the home page of the domain) I can check for that variable using the global PHP $_GET variable array and, if it exists, do something with it.

 
$passed_post_name = $_GET['post_name'];
// do something with the $passed_post_name variable

In order to open a specific tab or accordion on page A from page B, I need to setup my anchor links on page B to point to page A, but those links should also include a query string variable, in this instance the name of the accordion or tab item I want to open.

So, for the purposes of this topic my query string will something look like this

 ?et_open_accordion=et_pb_accordion_item_1 

or

 ?et_open_tab=et_pb_tab_1 

You’ll see that I am passing the class identifier of the accordion or tab item to open as the value. (more on this later)

Step 1: Making some jQuery changes

Let’s first take a look at the accordion ‘open’ snippet I posted in the original article:

jQuery(function ($) {
  //accordion
  $('#open-accordion-dance a').on('click', function(event){
    $('#my-accordian .et_pb_accordion_item_1 .et_pb_toggle_title').click();
    $("html, body").animate({ scrollTop: $('#my-accordian').offset().top }, 1000);
  });
  //tab
  $('#open-tab-dance a').on('click', function(event){
    $('#my-tabs .et_pb_tab_1 a').click();
    $("html, body").animate({ scrollTop: $('#my-tabs').offset().top }, 1000);
  });
});

The important thing to look at is the css class identifier for the accordion or item we’re triggering the click on, in this case .et_pb_accordion_item_1 or .et_pb_tab_1. See how this is the same as the value being passed in the query string above. What we need to do now is to be able to specify that value as a JavaScript variable somehow and pass that variable into the JavaScript, to trigger the click of our selected accordion item, when the page loads.

The second thing we will need to do is make sure that this code only fires, once the entire document has loaded. Currently it waits for you to click a link on the same page, but now we’ll be loading the page with the accordion or tab content and then triggering the click.

The change to the JavaScript looks like this:

jQuery(function ($) {
  $( document ).ready(function() {
    // accordion
    if (typeof openers.accordion !== 'undefined') {
      var accordion_element = '#my-accordian .' + openers.accordion + ' h5.et_pb_toggle_title';
      $(accordion_element).click();
      $("html, body").animate({ scrollTop: $('#my-accordian').offset().top }, 1000);
    }
    // tab
    if (typeof openers.tab !== 'undefined') {
      var tab_element = '#my-tabs .' + openers.tab + ' a';
      $(tab_element).click();
      $("html, body").animate({ scrollTop: $('#my-tabs').offset().top }, 1000);
    }
  });
});

Note how I have changed the et_pb_accordion_item_1 and et_pb_tab_1 to openers.accordion and openers.tab and instead of those variables being inside the class selector string they are being concatenated to the string (see, I told you this was a little more advanced). I’m also wrapping the entire thing inside a $( document ).ready(function() {} and removing the on(“click”) event handlers and checking if there is an instance of either openers.accordion or openers.tab. If either exists it will fire the relevant ‘open and animate to’ code.

 

Step 2: Mix in some PHP

Right, so now that we have this updated JavaScript we need to setup those openers variables, based on the query string. Do to this we need to do two things a) enqueue the JavaScript in the child theme and b) pass some PHP variables to the JavaScript. To achieve this we’ll put all our PHP code into a functions.php file of a child theme.

Instead of using the Divi Theme Options Code Integration tab for the JavaScript, we need to save it in a file in our child theme and hook a function into the wp_enqueue_scripts action hook (the same one used to enqueue child theme CSS). It looks something like this:

function my_theme_enqueue_scripts() {
wp_register_script( 'some_handle', 'path/to/myscript.js' );
wp_enqueue_script( 'some_handle' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_scripts' );

We also need to make the PHP variable available to the script. This is done by using the wp_localize_script function, which allows you to pass any variable from PHP to the JavaScript script you are enqueuing using wp_localize_script.

function my_theme_enqueue_scripts() {
    wp_register_script( 'some_handle', 'path/to/myscript.js' );
    $variable_array = array(
        'my_javascript_variable' =&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 'some value'
    );
    wp_localize_script( 'some_handle', 'javscript_object_name', $translation_array );
    wp_enqueue_script( 'some_handle' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_scripts' );

What this does is pass a PHP array of variables ( $variable_array  ) into the JavaScript layer as a JavaScript object ( javscript_object_name ) and makes them available to use in the JavaScript layer.

Finally we’ll need to capture the variables passed from the query string. That looks something like this:

$variable_array = array(); 
if( isset( $_GET['et_open_accordion'] ) ){ 
  $variable_array['accordion'] = $_GET['et_open_accordion']; 
} 
if( isset( $_GET['et_open_tab'] ) ){ 
  $variable_array['tab'] = $_GET['et_open_tab']; 
}

There are also some other things we need to setup, like defining path urls for enqueing files and setting up the Divi parent stylesheets. Again I’m not going to go into too much detail, but the final functions.php file looks like this:

define( 'PARENT_THEME_URL', trailingslashit( get_template_directory_uri( ) ) );
define( 'CHILD_THEME_URL', trailingslashit( get_stylesheet_directory_uri( ) ) );

function divi_child_theme_enqueue_styles() {

	$parent_style = 'divi-style'; // This is the 'parent-style'.

	wp_enqueue_style( $parent_style, PARENT_THEME_URL . 'style.css' );
	wp_enqueue_style( 'divi-child-style', CHILD_THEME_URL . 'style.css', array( $parent_style ) );

	$functions_script = 'divi-child-functions';

	$data = array();

	if( isset( $_GET['et_open_accordion'] ) ){
		$data['accordion'] = $_GET['et_open_accordion'];
	}

	if( isset( $_GET['et_open_tab'] ) ){
		$data['tab'] = $_GET['et_open_tab'];
	}

	wp_register_script( $functions_script, CHILD_THEME_URL . 'functions.js', array( 'jquery' ), '1.0', true );
	wp_localize_script( $functions_script, 'openers', $data );
	wp_enqueue_script( $functions_script );

}
add_action( 'wp_enqueue_scripts', 'divi_child_theme_enqueue_styles' );

Step 4: Putting it all together.

So, you have your functions.php file, retrieving the passed variables, setting up the javascript variables and enqueing the relevant javascript file to make it all work. All you have to do now is create a page with anchors that link to the correct location, including your query strings. And we’re all set.

To make it easier for you to test out, I’ve create a very basic Divi child theme, including all the above code, that you can just install, configure and use out of the box. You can grab this child theme demo from the GitHub page.

One thing to note, this article and child theme are for the purposes of explaining the basics of linking to open tabs or accordions. In the real world you should be considering escaping the query variables in the PHP to ensure no one injects any dodgy code into your site. This article is a good place to start.

Happy Divi-ing.

Update: Thanks to Nathan Duvall for pointing out how to manage this with Divi toggles.

(function($){
    $(window).load(function(){
        var et_hash = window.location.hash;
        if(window.location.hash) {
        $( '.et_pb_toggle' + et_hash ).removeClass('et_pb_toggle_close').addClass('et_pb_toggle_open');
    }
});
})(jQuery)

Credit: https://bernadot.com/divi-theme-how-to-open-toggled-modules-with-a-url-hashtag/

Filed under: Development, Divi, WordPressTagged with: , ,