Karen Attfield

Happiness Engineer at Automattic

  • Home
  • About
  • Contact

Introducing ‘Easeful’ – an accessible theme built on the Genesis Framework

December 16, 2018 by Karen Attfield Leave a Comment

The last project I was working on before starting work as a Happiness Engineer at Automattic was a simple theme built on the Genesis Framework, incorporating elements of accessibility. I was working on this until around March of this year, but didn’t want it to disappear, forgotten, never to be seen again. So I’ve now revamped my site, using this new accessible theme, which I named ‘Easeful’.

Easeful Screenshot

The theme is available on Github – feel free to download it and try it out!

Filed Under: Web development Tagged With: accessibility, theme

How to redirect a PDF in WordPress

August 9, 2018 by Karen Attfield Leave a Comment

 

So you want to redirect a PDF from your old site to your new WordPress site?

When you migrate your site, in order to maintain your search engine rankings you generally want to set up 301 redirects for URLs from your original site to the corresponding URL on your new site. Search engines are likely to continue to show your old site links in searches for some time, and you don’t want users heading to a 404 page.

Redirecting PDFs works in the same way as redirecting pages. In your .htaccess file, a typical 301 redirect section will look like this, for a site keeping the same domain name:

#Begin 301 Redirects
Redirect 301 /sub-page/sub-sub-page https://www.example.com/new-sub-page/new-sub-sub-page/
#End 301 Redirects

And like this for a site changing domain name:

#Begin 301 Redirects
Redirect 301 http://www.old-site.com/sub-page/sub-sub-page https://www.example.com/new-sub-page/new-sub-sub-page/
#End 301 Redirects

For PDFs, the process is exactly the same. Where it differs is when PDFs have been uploaded in the past with spaces in the file name (generally on older sites where the spaces have been retained in the file name). This means the original PDF URL was something like http://www.old-site.com/wp-content/uploads/2014/06/a%20fancy%20title.pdf. The problem is that the %20’s are not recognised when this URL is added to the .htaccess file. The way around this is to enclose the original URL in quotes, keeping the original spaces. Here is an example:

#Begin 301 Redirects
Redirect 301 "/wp-content/a fancy title.pdf" https://www.example.com/a-new-fancy-title.pdf
#End 301 Redirects

Note: This works on Linux servers. If you are using an Apache server and still having issues, check out this article.

Filed Under: Web development

Live routes with Google Maps API

January 13, 2018 by Karen Attfield Leave a Comment

(Article updated 9th February, 2018)

My latest project is a WordPress plugin, Maps for BuddyBeacon, which pulls location (beacon) data in from a route tracking app (ViewRanger), and displays this on a Google Map.

I was inspired to create this as a challenge after being involved in finding a solution to display the live route for Simon Clark who ran around the coast of Britain raising funds for charity. For that I used Social Hiking to embed a map in the charity website, and was so impressed I wanted to create a more simplified version for WordPress sites. Social Hiking have just announced that they will be closing at the end of May this year, unfortunately – they were a great resource that allowed hikers, cyclists, and walkers to share their adventures, and Phil Sorrel (the brains behind it) inspired me in terms of what a developer can create to help a community.

Example Maps for BuddyBeacon display
The map display

I recently put part of the code on CodePen to replicate pulling live location data and displaying the route, and it quickly became my most viewed pen. So, I thought I would briefly go through some of the challenges, and solutions in creating this.

The goal: Gather all information from the user needed to generate a map with a route, and display it on the front-end of a WordPress site via a shortcode.

The challenges

  • Create multiple settings pages in the WordPress dashboard to gather data such as API keys, map and beacon display preferences, and also to show an editable table of all existing maps. Data needed to be validated and sanitized, and on the page to add map functionality there needed to be default options in place.
  • Allow the user to set a start date and an end date, or set the end date to current to show live routes.
  • When displaying the map with the shortcode, include an option to show an information box with the map title, date range, and total distance covered (calculated in either miles or km, as the total distance between each beacon submitted).
  • Allow multiple maps to display on any page.
Maps for BuddyBeacon 'manage maps' page
The ‘manage maps’ settings page

Some of the solutions

  • The table functionality in the ‘manage maps’ option page was created by extending the WP_List_Table class.
  • The datepicker had to include the ability to choose the specific time as well, as the user may have more than one route on one day, so I used Bootstrap’s Datetimepicker.
  • Adding multiple maps to one page involved a significant re-write as I’d built the plugin based on just one map per page. It involved creating a dynamic wp_localize_script variable for each unique shortcode ID, passing that to Javascript, looping through each shortcode ID to see if it matched the dynamic ID added to the ‘map-canvas’ class in HTML, and then running the code with the variables specific to each map.
  • Another issue was discovered on testing the plugin – the map sometimes showed and sometimes didn’t on live sites. This was due to how the scripts were being loaded. The custom JS script to load the map, beacons and route was a dependency on the Google API script which was called afterwards, yet the script loading order wasn’t always correct (or rather, the custom JS script wouldn’t be completely loaded before the Google API script started). This was largely resolved with setting the dependency as above, yet the maps would not load in Internet Explorer or Microsoft Edge. My workaround was to use Javascript’s setTimeout() function and detect if the map function (initMap) had been called after 3 seconds had passed. If not, the function was called again:
    setTimeout(function() {
    
    		if (initMap.called) {
    		    return;
    		 }
    		else {
    			initMap();
    }, 3000);
    
    window.initMap = function() {
    		initMap.called = true;
            //Rest of code

The Maps for BuddyBeacon plugin is available on the WordPress repository, and you can also find the source code on GitHub.

Future additions, time permitting:

  • Integrating Twitter and other social media platforms so that individual beacons can hold links to social media posts and images.
  • Creating the ability to manually delete (or add) beacons. Update (9th February 2018): The ability to delete beacons has been added.
  • Provide the option to display the map output as a Gutenberg block as an alternative to using a shortcode.

I would love to collaborate with any other developers who would be interested in contributing to and growing this plugin.

Filed Under: Web development

Adding datepicker to a WordPress form

June 12, 2017 by Karen Attfield Leave a Comment

Customizing custom-made or plugin forms with datepicker

jQuery UI Datepicker
jQuery UI Datepicker

So you’ve developed a basic contact form on a client’s site (or installed a lite contact form plugin, such as WPForms Lite or Contact Form 7), and they love it. Several months later, they get in touch with you because the business is expanding and they need a booking form added, and want a datepicker included so that site visitors can easily select dates whilst filling in the form.

No worries!

You have several options available to you – if you used a plugin you could either upgrade to a premium plan of the plugin you are using (for example WPForms basic) or add the extra functionality yourself. While you and your client may decide it’s better to pay a yearly price for a premium option, this is only hassle free if you went with a plugin that allows for upgrades, such as WPForms. Yes you could install a new contact form plugin, but do you really want two contact form plugins on your site?

More than likely you’ve added CSS styling to your forms, and you would have to start again with the new form. Some plugins such as Contact Form 7, require you to add another plugin to get the datepicker functionality as well (and at the time of writing the support for that plugin doesn’t look so hot) – and again, do you want all these extra plugins on your site, potentially causing issues if the developer doesn’t keep them updated? So, you decide to add the functionality yourself.

Editing the input field

So what we want to be able to do is to show the datepicker when we click on the ‘booking date’ input field. We then want to be able to select a date and for that date to be displayed in the field.

The first step then is to add an id for the form field you would like a datepicker added to. If you’ve custom built your form, just add the id to the input field you want to use. Let’s name the id #booking-date for the sake of this article. In it’s most basic form, your input field should look something like this:

<input id="booking-date" name="booking-date" type="text" />

This may be trickier if you used a plugin. For example, WPForms will allow you to create a class for your booking date field, but this class name is applied to the field container rather than the specific input field. Add the class booking-date to the field container – you will be able to access the input field directly using the jQuery extenstion: '.booking-date > :input' (we’ll use this in the jQuery function later).

In Contact Form 7, you can add an id to the field you want by adding id:booking-date within the square brackets for your date field.

Note: you can use Contact Form 7’s default date functionality – this implements the date attribute in HTML5. This article assumes you want to use jQuery’s datepicker for various reasons including styling and date formats, as well as browser compatibility. You can find out more about HTML5’s date attribute here ).

Enqueue the styles and scripts

The next thing to do is enqueue the datepicker script in your functions.php file, and also enqueue the datepicker theme styling. In functions.php, add the following to your existing wp_enqueue_scripts function (we don’t need to enqueue jQuery as WordPress includes and loads it’s own version of the jQuery library automatically):

wp_enqueue_script('jquery-ui-datepicker');
wp_enqueue_style('jquery-style', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');

Trigger the datepicker function

The final thing to do is create a function in your functions.php file that will run the jQuery code that will trigger the datepicker. You can also do this in a separate Javascript file and enqueue the script if you wish. As we want the script to load in the footer, we’ll hook the php function onto the wp_footer action hook.

So at the bottom of our functions.php file we’ll add the following:

function add_datepicker(){ 
    ?>
    
    jQuery(document).ready(function(){

        $bookingdate = '.booking-date > :input';   // use this if adding a class name to the input field container or $bookingdate = '#booking-date';  
} 

add_action('wp_footer','add_datepicker',10);

How does this work?

What exactly is this function doing? The PHP function includes a Javascript function which starts by creating a variable that represents either the id name of the input field (for example if you are using a custom built form or a plugin like Contact Form 7), or the class name of the input field container if you are using the WPForms Lite plugin.

Before clicking the input, we hide the datepicker.

On clicking that input, we set up the datepicker, and then show it.

And that’s all there is to it. You can customise and style the datepicker to your heart’s content (check out the jQuery datepicker API documentation to explore the API in depth). Some time back I created a demo booking form on a static HTML page using datepicker – you can check out the code on Github for some customisation ideas.

Disclaimer: The link to WPForms on this page is an affiliate link, should you decide you’d prefer to purchase any of their premium plugin versions.

Filed Under: Web development

Custom post types & advanced custom fields in Genesis (part 2)

April 15, 2017 by Karen Attfield Leave a Comment

Setting up the custom fields

Continuing on from the first part of this two part article where we set up a custom events post type, below we’ll look at adding custom fields with the Advanced Custom Fields plugin.

The first step is to install and activate Advanced Custom Fields. Then, add a new group (give it a name of your choice, for example Event Details).

Advanced Custom Fields group set up screenshot

We’ll create one field for now, in which a date can be selected. That date represents the date that the event is considered a past event, and once that date is reached, we then want the event to show up on a different page. To set this new field, give it a label such as Event End Date. The field name will be automatically generated. Set the field type to Date Picker and add some instructions, such as ‘Mark the date at which the event will be considered a past event’. Mark whether or not you want this as a required field, and make sure you’re happy with the default date format.

In the location box, set the rule to show this field group if the post type is equal to events, and under options set the style to standard.

Advanced Custom Fields location and options screenshot

Now we need to add the functionality that begins the process of separating past events from current/future events. We do this by modifying the pre_get_posts action hook, adding a meta query and creating a $compare variable to compare today’s date with the date selected. At the same time we can also use pre_get_posts to add a limit to the number of posts we want to show per page. This functionality is added to functions.php, as pre_get_posts won’t work if used on template pages.

In our functions.php file we add the following:

/** Customising the custom post type query (comparing today's
 * date with the date selected, and only showing a maximum of 3 posts per page)
 */
function event_post_order( $query ){
    // if this is not an admin screen,
    // and is the event post type archive
    // and is the main query
    if( ! is_admin()
        && $query->is_post_type_archive( 'events' )
        && $query->is_main_query() ){

        // if this is a past events view
        // set compare to before today,
        // otherwise set to today or later
        $compare = isset( $query->query_vars['is_past'] ) ? '<' : '>=';

        // add the meta query and use the $compare var
        $today = date( 'Y-m-d' );
        $meta_query = array( array( 
            'key' => 'event_end_date', // this is the field name for the date picker field
            'value' => $today,
            'compare' => $compare,
            'type' => 'DATE'
        ) );
        // set the meta_query argument to equal the $meta_query array created above
        $query->set( 'meta_query', $meta_query );
        // set the posts per page to 3
        $query->set( 'posts_per_page', '3' );
    }
}
add_action( 'pre_get_posts', 'event_post_order' );

Now for the juicy part. To create a separate page for past events, we need to set up a rewrite tag and a rewrite rule:

//This function creates a page (past) to show all 'events' post types whose end-dates have passed.
function event_archive_rewrites(){

    add_rewrite_tag( '%is_past%','([^&]+)' );
    add_rewrite_rule(
        'events/past/page/([0-9]+)/?$',
        'index.php?post_type=events&paged=$matches[1]&is_past=true',
        'top'
    );
    add_rewrite_rule(
        'events/past/?$',
        'index.php?post_type=events&is_past=true',
        'top'
    );

}
add_action( 'init', 'event_archive_rewrites' );

Looking good! Credit goes to Milo for the basis of the previous two code snippets.

Now for the final touch. In our Genesis theme, the title of our past events page is still showing up as Events – all we’ve done is change the url, so apart from now only showing past events, everything else will be the same. We can easily change that title to Past Events with the following code snippet in functions.php:

function event_archive_url() {
	
	$url = $_SERVER['REQUEST_URI'];

	// if 'events/past' exists in the url, then add text to the beginning of the title
	if (strpos($url,'events/past') !== false) {
   ?>
   <style>
     .archive-title::before {
       content: "Past";
      }
   </style>
   <?php 
   }
 } 

add_action( 'init', 'event_archive_url' );

The end result is a custom events post type with a custom field that will allow users to select an ‘expiry’ date on the event, after which events show on a ‘Past Events’ page, cleanly separating current & future events from past events.

Filed Under: Web development

  • 1
  • 2
  • Next Page »

Copyright © 2019 · Easeful