Hooking into the onclick even 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 ‘1’.

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

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

Happy Diviing.

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/

WordCamp Cape Town 2017

WordCampCapeTown2017

So last year I blogged about my list of resolutions for the new year. As with most resolutions it was a long list of the things I want to do differently in the new year, with very little grounding in reality. Reading that post now I can’t help wonder how I thought I was going to manufacture all that extra time!

Two days ago I sat staring at all the Make Slack channels I had joined in the course of the year and the realisation dawned that I was trying to keep too many fingers in too many pies when it comes to contributing to WordPress.  It struck me that I had to choose one (or maybe two) avenues within which I want to contribute back to WordPress this year and focus my spare time on those.

What I didn’t realise then, but I do now, was that I had already made the decision of what to focus on this year, merely by my actions last year, things that had already been set in motion during 2016. Once I realised that, it was very easy to leave all the other channels and look ahead to my journey with WordPress in 2017 with renewed purpose.  That purpose, building the community.

Which leads me to the real point of this article, an announcement I’ve been sitting on for a few weeks now and one that I’m happy now share with the world. I’ve applied (and been accepted) as the organiser for WordCamp Cape Town this year. It is a role I didn’t expect to take on until 2018 but circumstances have sent this my way and I’m happy to take on the challenge.

I’ll be blogging about my experiences here, mostly to record the journey from my own perspective but hopefully to educate and inspire others to either join, start or become a part of their own WordCamp’s around the world.

So here’s looking forward to WordCamp Cape Town 2017. Hopefully I’ll meet you there and we can share a WordPress story, or even just a coffee.

My 2017 WordPress resolutions.

Horizon

Last year I caught the State of the Word on WordPress.tv after the event. This was mainly because a) I was fairly new to all things WordPress and b) I didn’t actually even know it was a thing. This year I knew about WCUS well in advance so I registered for the live stream and planned my life to be able to watch Matt’s talk. I am so glad I did.

The new things planned for WordPress in 2017 are really going to shake things up. I’m not here to report on those changes, I’ve leave that up to people way better than me, Brian  from PostStatus and Sarah from WPTavern.

My take away from Matt’s talk was a deep introspection into what areas of WordPress I want to grow into next year. My goals this year were a) become fully self employed b) focus on WordPress as a platform c) speak at WordCamp. I’ve managed to achieve those goals, so it’s time to push myself a little harder in 2017.

As Matt put it so well (quoting Krista Tippet)

“We only learn to walk when we risk falling down, and this equation holds — with commensurately more complex dynamics — our whole lives long.”

It’s time for me to fall down a bit (again).

A more stable work environment

This past year has had it’s ups and downs (in more areas than one). For 2017 I want to focus on doing three things better.

1) A better work/life balance
2) A 25%/70% split on client work and plugin development
3) Project estimation

That last one is pretty important. One thing I have learned is that I still (after 12 years of doing this) tend to under estimate my time when it comes to project work. For 2017 I want to manage this better, not only when it comes to how long I think something will take, but also to value my experience more. This in in turn will allow me to split my development time in a way that I control (not the projects I’m working on) and be able to spend more time with my family

5 for the future.

You’re probably wondering about that 25%/70% split above, and where the other 5% is. That 5% of my development time I want to use in contributing better to WordPress. Some of the areas I want to become more involved in next year include:

WordPress Core, Calypso

Two areas that fall under the 5 for the future banner above are core and Calypso. By the end of 2017 I want to have contributed at least one patch to WordPress core and one patch to the Calypso project. This will help me become both a better WordPress developer and force me to learn React and Redux, two areas I have wanted to look into for some time now.

WordPress theme review

The WordPress theme review team is extremely under supported so I want to try and learn how to review a theme with the goal of being able to actually do one theme review once a month. I don’ know how long it will take me to get up to speed, but I need to start somewhere.

PolyGlots

This year saw the inclusion of a new locale for South Africa (Xhosa) and two new locales soon to be submitted. While I do not speak these languages I am excited to assist the new Global Translation Editors in getting these languages up and running for WordPress.

WordCamp

This year I spoke, next year I plan to be a part of it, either as a volunteer or a member of the organising team. Watch this space…

REST API powered plugin

Next year I want to either build a new plugin or rewrite an existing plugin that uses the REST API for at least some part of it’s functionality. I already have an idea for which plugin I will be doing this with and I hope to get started on it very early in the new year.

Twenty Seventeen theme

Another thing I would like to do is have my personal blog run the Twenty Seventeen theme. I’ll probably need to spend a bit of time learning all the new stuff that has been released, but I am hoping this will lead to a continuing trend of my blog always running the official WordPress theme.

WPHackerCast

This is a personal project of mine, a podcast by developers aimed for developers. I have a specific idea in mind here and it’s really a passion project that I know I will enjoy and I hope you all do to.

 

That’s a whole list of things I want to achieve. I’m not fooled into thinking I’ll be able to do all of them, but at least I can try.

What are your resolutions for the new year?

Remembering Why – Part 2

Horizon

Some time ago I wrote a blog post on remembering why I got into developing web applications in the first place. At the time I was struggling to find my focus as a developer. I’m happy to report that since then I have (more or less) figured that out.

I’ve since realised that one of my problems is that when I started out, I didn’t have a vision, mission statement or personal creed for why I wanted to do what I am doing. I just knew that I wanted to do it. Being on my own I didn’t think of such things, I tend to just rush in where angels fear to tread and then figure it out as I go along.

Today I was introduced to the Automattic creed and I was blown out of my socks. It really resonated with me, as every point in the creed is something that I believe in, a reason why I became a web developer and why I support and believe in open source as more than just a decision on software licensing. So, going into 2017 I am going to remind myself of this as much as possible.

Here is the Automattic creed:

I will never stop learning. I won’t just work on things that are assigned to me. I know there’s no such thing as a status quo. I will build our business sustainably through passionate and loyal customers. I will never pass up an opportunity to help out a colleague, and I’ll remember the days before I knew everything. I am more motivated by impact than money, and I know that Open Source is one of the most powerful ideas of our generation. I will communicate as much as possible, because it’s the oxygen of a distributed company. I am in a marathon, not a sprint, and no matter how far away the goal is, the only way to get there is by putting one foot in front of another every day. Given time, there is no problem that’s insurmountable.

That’s pretty powerful stuff!

Turn any button into an Add to Cart button

Turn any button into an add to cart button

The thing I love about blogging about WordPress is how many great questions come out of the comments of previous blogs.

Today, on my post on ‘Adding the cart button to your shop pages in Divi‘, I was asked the following:

I am trying to put an Add-to-cart button in the main Divi slider. Now Divi slider only gives an option to input a URL for the default slider button. But i was wondering is there a way to modify that button and convert it into a WooCommerce AddtoCart button?

So, there’s no way to make a slider button (or any other button for that matter) an add to cart button. But what you can do is replicate the Add to Cart functionality on any button by entering the right url.

What a lot of people don’t know is that all the Divi add to cart buttons are doing is performing the add to cart action behind the scenes. To add a product to your cart all you need to do is pass a a variable called ‘add-to-cart’ with a value that is the id of a product and WooCommerce will add that product to your cart.

So lets say your site url is http://www.myawesomeshop.com/. To turn that url into an add to cart url you just need to add ?add-to-cart=[ID] to the end of it, where [ID] is the id of the product you want the customer to add to their cart.

http://www.myawesomeshop.com/?add-to-cart=[ID]

If you aren’t sure what the product id is, just look at any product. It’s the value that appears next to ID when you hover over a product. If you edit a product, its the value for post that appears in the address bar

http://www.myawesomeshop.com/wp-admin/post.php?post=[ID]&action=edit

Also, make sure you include the trailing slash at the end of the site url, otherwise things won’t work.

So that’s it, append ?add-to-cart=[ID] to the end of your site url ( don’t forget the trailing slash ) and turn any url into an ‘add to cart’ url.

Happy Diviing.

 

Codeable Review – October 2016

work-review

October marks my second month at Codeable. My first month was very quiet, mostly because I was still busy with other things in September, including WordCamp. I also took my time getting into the Codeable process, commenting on only a few smaller tasks. I closed my first small task mid October, so I’m considering October as my first official month as a Codeable developer.

It should be noted that due to my other commitments I only have an average of about 20 WordPress development hours available in a week, which I try to split between plugin development, blogging and Codeable work. This means I tend to focus on smaller projects that don’t require my time for longer than about 4 – 6 hours a day, unless the deadline is very flexible.

Fellow Codeable expert, WordCamp speaker and all around nice guy Nathan Ello believes “transparency trumps secrecy” and I tend to agree with him. With that in mind, below you will find my income and client reviews from Codeable for the month of October.

Show me the money

First, a quick calculation. Based on the minimum number of hours I have available for Codeable development (4) and the Codeable minimum suggested hourly rate of $60, I am aiming to earn about $720 per week or about $2800 per month. For some this may not be much, but for my situation it is an acceptable amount (for now). I am also basing my income for the month on the amount I can withdraw on the 25th of that month, so any project I get hired for during or after that day, or that gets paid out after that date, gets moved into the following month.

So how did October go? To be honest it wasnt amazing, but I am happy with it. I’m already on a good path to more than double my October income in November and I’ve more or less figured out a good balance between Codeable work and my other ventures.

My total Codeable income for October is $504.50. Now as you will agree that’s only about a quarter of my target amount above, but I really only closed those projects in the last week of October. I was also hired for a task of about $1000 in October that is still ongoing and I have another project of a little over $1000 lined up for November. So November is already close to my target within the first week.

Happiness report

More important than the money is how my clients view my work. As I don’t have a lot of closed tasks for October I don’t have a huge amount of reviews on my profile, but those that I do have are very positive.

“Jonathan is The Best! Very knowledgeable and Very Professional. He is the right man for all Tasks. Glad to find him here. :)”

“Perfect teamwork. Clear communication and perfect coding.”

“A star! Smashing tutor”

A few thanks

Getting through the first few months at Codeable wasn’t easy with my specific situation. I had a few ups and downs, and I probably wouldn’t have made it this far without the help of the Codeable support team (Chris, Raleigh, Liam, David and Per) and a few fellow developers (Justin, Robin, Panos and anyone else I’ve forgotten to mention, who make hanging out on the Codeable Slack a blast) who helped and guided me along the way. A special shout out to Justin who had a nice little chat with me on Slack one day and gave me the push I needed to get back up in the horse, thanks man!

October was OK, November is already looking good, here’s to wrapping up the year on a great footing to kick off 2017 with a bang at Codeable!

4 WordCamps in 4 Months

WordCamp

Last year at WordCamp I decided I would speak at the next one, this year I did just that. So when I heard that there would be 3 new WordCamps happening in Africa this year (one in Johannesburg, one in Nairobi and one in Harare) I decided on the spot I want to attend all three.

In deciding to do this I realised that, with my attendance of WordCamp Cape Town in September, I’d effectively be able to attend a total of 4 WordCamps in 4 months (Johannesburg in November and Nairobi and Harare in December). The downside (as always), finding the money to do it.

As a self employed developer finding $2000 – $3000 to cover flights, accommodation and general expenses for the three extra trips is not easy. As such I am reaching out to the greater community, in Africa and internationally, to assist me in my plan.

Over at Elegant Marketplace I developed a really small plugin (that was released for free) which simply adds a ‘Next’ and ‘Previous’ link at the end of every blog post. For the month of November I’ve changed the pricing model to a ‘choose your own price’ option, with a minimum of $2 and a suggested price of $5. Elegant Marketplace has kindly offered to give me the full proceeds of the sale of this plugin for the month of November, waiving the usual management fees I pay for my other products.

If I can get 600 people to buy this plugin I’ll be able to cover the costs of my trips. Even if you never use the plugin, or you could really write one your own, I’d appreciate your support in making this trip possible.

You can read more about the trip and how it came about in my Elegant Marketplace blog post or you can just go ahead and buy the plugin here.

Thanks.

Why upholding the GPL might be so important to Matt.

Freedom

For those of you who don’t follow WordPress news and updates as I do, over the weekend Automattic CEO Matt Mullenweg wrote a post accusing WordPress competitor Wix of stealing code. The CEO of Wix responded shortly thereafter. It’s been an interesting few days for WordPress and the GPL, with some people supporting and praising Matt for his post, while others have suggested that his post indicates a lack of leadership or that he was foolish calling out Wix publicly.

I’m not going to comment on either side. Nor will I be able to successfully comment on the legalities of different open source licenses. What I would like to do is offer some insight as to why I believe Matt is such a strong defender of the GPL.

Last night I started reading Milestones: The Story of WordPress. It traces the history of WordPress all the way back to the b2/cafelog days. In chapter 2 it talks about the original b2 developer, Michel Valdrighi, and his reasons for choosing the GPL license.

“It was important to Michel that b2 remain free, even if he stopped working on the project. He also wanted his code to remain free if other developers took it and used it in their own project. He recalls now that “at the end of that elimination process, GPL remained. It helped that there were already some projects using it, as I didn’t want the code to end up abandoned and forgotten because of the choice of an exotic license.”

Michel’s choice of license was prescient. Under a GPL license, software can be forked, modified, and redistributed. If development stops (as it did with b2), the ability to fork, modify, and redistribute can prevent software from becoming vaporware.”

It is vital to note that the freedoms provided by the GPL meant that Matt and Mike (the co founders of WordPress) were not only allowed to fork b2, but were allowed to study it, edit it, improve it and release it back to the community for further study, editing and improvement. All that had to be maintained through each iteration of the software was that it retained the GPL license and the freedoms it provided.

It’s probably safe to say that without the GPL license, Matt and Mike may not have chosen to fork b2, WordPress may never have existed, 25% of the web would be run on something else and the millions of people around the world (including me) would not have jobs today.

So, thanks Matt, for having the moral character to stand up for the GPL and it’s freedoms, the same freedoms that allowed you to create WordPress in the first place.

Sometimes the right thing to do isn’t always the popular thing to do.