Adding page name to the body classes in WordPress

I seem to always have to remind myself of this one… whether it is someone else’s theme I’m dealing with, or an Underscores starter, or for whatever reason the body classes seem insufficient, I always like having the page name in the body classes. This makes it easy to target something that may need to happen on a particular page, and safeguards against the client deleting and re-establishing that page. In any event, if you need the same this is a simple fix. The body_class() function can be filtered and elements added to the array there. You can of course use the page slug or any other detail from the $post object.

//Page Slug Body Class
function add_body_class( $classes ) {
global $post;
if ( isset( $post ) ) {
$classes[] = $post->post_name;
}
return $classes;
}
add_filter('body_class','add_body_class');

PHP copyright and current year

Often in the footer of your site you want to write something like: “© 2015 Mick Follari”. But you also don’t want to have to remember to go change it every year, or to teach your clients how to do it. Another thing I found this useful for is in one case I had a client I needed to have an image header with the year built in to it, like “2015 Adventure Film Festival”. I pre-made 5 years of headers and gave them names with the year in them and used the PHP year in the img src filename so they would automatically update on Jan 1.

Many people just want this snippet:

&copy; <?php echo date("Y"); ?>
&copy; <?php echo date("Y").' -YourNameHere'; ?>
&copy; 2012-<?php echo date("Y").' -YourNameHere'; ?>

The first displays just the year, the second adds your name or company, the third shows a range (like “© 2012-2015 Mick Follari”).

There is a long list of arguments you can use to configure the date if you’d rather more than just the year. Here’s the index.

This is a pretty basic thing, but I find people are always asking or looking up how to do. Since most of my sites are in WordPress, I’ll mention first that you should create a Child Theme, then alter the footer.php from your Parent theme in there. If you need to learn more about Child themes there’s plenty out there (and I’ll make a new blog post about it), but start here.

Once you have your Child Theme, copy the footer.php from your Parent theme into the new folder, and start editing the place where it shows the copyright. If the Parent theme is using a filter or hook to write in the copyright, then you only need to unhook that function, and write your own to replace it. That’s another post…

 

Woocommerce Product Variation Description with dynamic loading

Recently I had a project where a client needed to offer a variable product with extra information about each variation displayed, and this needed to change as the selector changed the variation. The product page would be linked to from another page on their site, with the desired variation pre-loaded in the drop-down selector on arrival. However, once there you could of course play with the drop-down to select other variations.

Let’s break down what I did to get everything working.

Here’s a quick summary:

  • create a textarea that gets added to the variations editor in the Woocommerce product
  • hook it in properly so it responds to javascript and normal page loading
  • get the contents of the textareas and inject them into the product page on the front end
  • hide all of them except the one we want to show based on the drop-down selector

The variable product custom field text area:

First, I wanted to create a textarea for each product variation for the client to be able to enter a description. Originally, I simply grabbed a plugin that did just that. But after we had a bunch of nightmares with malware and site hacking, we wiped everything and started over on a new host where we wanted to stay as clean as possible, limit our plugins, and by then that plugin had been removed from the repository. I found great instruction on adding custom fields to variable products by Remi Corson which looked easy to implement. Using his post as a guide I added a function to create the textarea and hook in properly to Woocommerce. And, as he points out, we have to deal with the Ajax creation of new variations, so everything is done twice as you’ll see. This goes in the functions file.


//Product Variation Description

//Display Fields
add_action( 'woocommerce_product_after_variable_attributes', 'variable_fields', 10, 3 );
//JS to add fields for new variations
add_action( 'woocommerce_product_after_variable_attributes_js', 'variable_fields_js' );
//Save variation fields
add_action( 'woocommerce_process_product_meta_variable', 'save_variable_fields', 10, 1 );

//Create new fields for variations
function variable_fields( $loop, $variation_data, $variation ) {
?>
 <tr>
  <td>
   <?php
   // Textarea
   woocommerce_wp_textarea_input(
    array(
     'id'          => '_textarea['.$loop.']',
     'label'       => __( 'Description', 'woocommerce' ),
     'placeholder' => '',
     'value'       => get_post_meta( $variation->ID, '_textarea', true ),
    )
   );
?>
 </td>
  </tr>
   <?php
}

// Create new fields for new variations
function variable_fields_js() {
?>
 <tr>
  <td>
   <?php
   // Textarea
   woocommerce_wp_textarea_input(
    array(
     'id'          => '_textarea[ + loop + ]',
     'label'       => __( 'Description', 'woocommerce' ),
     'placeholder' => '',
     'value'       => '',
    )
   );
?>
  </td>
 </tr>
<?php
}

//Save new fields for variations
function save_variable_fields( $post_id ) {
 if (isset( $_POST['variable_sku'] ) ) :
  $variable_sku          = $_POST['variable_sku'];
  $variable_post_id      = $_POST['variable_post_id'];
  // Textarea
  $_textarea = $_POST['_textarea'];
  for ( $i = 0; $i < sizeof( $variable_sku ); $i++ ) :
   $variation_id = (int) $variable_post_id[$i];
    if ( isset( $_textarea[$i] ) ) {
     update_post_meta( $variation_id, '_textarea', stripslashes( $_textarea[$i] ) );
    }
  endfor;
 endif;
}

The code gave me this in my variable products:

variable-descriptions

Get the Description to use on the Product Page:

To get the description I had created for them and add it to the product page, I’m using the all-powerful get_post_meta, and also grabbing the price, since they are all different. I’m doing this from the functions file and hooking in to the ‘before add to cart’ in Woocommerce. As you’ll notice this is going to write them all out on the page, which is not what we want, but I added some javascript to hide them all, then turn on each one depending on what’s selected in the drop-down. This also goes in the functions file.


function my_theme_function_woocommerce_before_add_to_cart_form() {
 // get the product
 global $product;
 // Get the post IDs of all the product variations
 $variation_ids = $product->children;
 // check if we have variations
 if ( empty( $variation_ids ) )
  return;
 // walk the variations
 foreach( $variation_ids as $variation_id ) {
  $variable_product= new WC_Product_Variation( $variation_id );
  $description = get_post_meta($variation_id, '_textarea');
  $price = $variable_product ->regular_price;
  echo '<div id="variation-' . $variation_id . '" style="display: none;" class="camp-description">';
  echo '<p>'.$description[0].'</p>';
  echo '<b> $'.$price.'</b>';
  echo '</div>';
 }
}
add_action( 'woocommerce_before_add_to_cart_form', 'my_theme_function_woocommerce_before_add_to_cart_form', 5 );

jQuery to show the one we want:

I needed this solution fast, so I resorted to some jQuery trickery to display the one description we want out of all the descriptions hidden on the page, based on what option was selected in the drop-down. This goes in a custom.js file that adds various extra jQuery I need on the site. It should be wrapped in the usual ‘jQuery(document).ready(function ($) {}’.


//Summer Camp products get variation ID to show/hide descriptions
setTimeout(function(){
 variationid= '';
 if(typeof $('input[name=variation_id]').val()  != "undefined" && $('input[name=variation_id]').val() !== null) {
  variationid = $('input[name=variation_id]').val();
  $('div#variation-'+variationid).show();
 }
}, 100);

setTimeout(function(){
 $('body').on('change', '#camps',function(){
  $('div#variation-'+variationid).hide();
  setTimeout(function(){
  variationid = $('input[name="variation_id"]').val();
  $('div#variation-'+variationid).show();
  }, 100)
 });
}, 200);

SIDE NOTE: to land on the page in the first place the user is clicking through from another page. The link they click is set up to leverage Woocommerce pre-filling the drop-down with a certain variation. The href in the link looks like this:

/summer-camp-registration/?attribute_camps=early-childhood-session-1-latin-celebrations

 Wrap up:

I’m sure there are some more elegant ways to do things, but this got me what I needed in a hurry, and seems to be working fine. I’m not crazy about having the timeouts in the js to allow for all the other Woocommerce js to work, but again it’s not too much of a drag on the user experience I think. If I get time I’ll go through more explanation of how things work on here. Here is the product page where you can see this working: https://www.waldorfsandiego.org/summer-camp-registration/?attribute_camps=early-childhood-session-1-latin-celebrations