Remaking WP Eagle’s Dart Averages Calculator w/ the WP REST API

Share this:

I’ve watched Alex from WP Eagle on and off for a while on YouTube, so I’m familiar with his content—which is how I came across his calculator tutorial to begin with. In his tutorial, he shows you how you can make a simple calculator using Gravity Forms—a premium plugin for creating custom forms.

I thought it was a great example for an article like this, given it’s lack of complexity—and that being able to make these sorts of tools to increase the link-worthiness of content is something that most niche site marketers could likely benefit from. You can see the original article on WP Eagle’s site here and his darts average calculator here.

With the intro out of the way, let’s get into the meat of this article—how to remake this simple calculator using the WordPress REST API.

You don’t always need a plugin—use the WP REST API instead

The WP REST API is criminally underused. The possibilities it offers to extend the functionality of a WordPress site are near-infinite, letting you building everything from calculators and tools, to APIs, and even fully-fledge products and services—the sky’s the limit really.

I think it’s a bit of a shame that so many decide to load up on unnecessary, third-party plugins that eat into their budget and add bloat to their websites—often for super simple functionality that could be easily achieved with your own plugin. This is the point of this article, demonstrating that you don’t always need to hack together a solution from some plugin, and can instead make something better yourself.

While the example below is pretty basic, it can be reworked and repurposed to make any sort of calculator really—it should serve as a fairly good jumping off point for anyone new to the WP REST API and interested in creating their own tools and adding other, similar functionality to their WordPress sites.

The dart averages calculator in action

The finished calculator I’ll be showing you how to make can be seen below—give it a go to see it in action for yourself.



The code

I’ll do my best to explain how this all works, but—and as I’ve said often on this blog—my content is all about working examples, and not so much tutorials. So I apologize in advance if anything isn’t quite as clear as it could be.

Working with the WP REST API is also fairly new to me, so I’m by no means an expert on this stuff—but if you have any questions or are unsure of anything here, please let me know in the comments and I’ll do my best to respond.

plugin.php

The first part of this file is the “darts_calculator_script_and_style“—which is pretty self explanatory, it registers the JS and CSS files (that we’ll get to shortly) that the calculator uses.

function darts_calculator_script_and_style() {
    wp_register_script( 'darts_calculator_js',plugins_url( 'js/darts_calculator.js', __FILE__ ), '', '', true );
    wp_register_style( 'darts_calculator_css',plugins_url( 'css/darts_calculator.css', __FILE__ ));
}
add_action( 'wp_enqueue_scripts', 'darts_calculator_script_and_style');

The “darts_calculator_shortcode” sets up the shortcode which renders the html file that contains the calculators form and adds the CSS and JS to any page where the shortcode is used.

It also sets the name of the shortcode—which is “darts_calculator“—used when adding it to a page in your WP admin.

function darts_calculator_shortcode() {
    if (!is_admin()) {
        ob_start();
        require plugin_dir_path( __FILE__ ).'html/darts_calculator.html';
        wp_enqueue_script('darts_calculator_js');
	wp_enqueue_style('darts_calculator_css');
        return ob_get_clean();
    }
}
add_shortcode('darts_calculator', 'darts_calculator_shortcode');

The “darts_calculator_route” function sets up the custom endpoint in the WP REST API and sets the callback function (“darts_calculator“), which we’ll get to next.

function darts_calculator_route() {
    register_rest_route('dartsCalculator', 'v1', [
        'methods'  => WP_REST_SERVER::READABLE,
        'callback' => 'darts_calculator'
    ]);
}
add_action('rest_api_init', 'darts_calculator_route');

Last up for the plugin.php file is the “darts_calculator” function—which as we just mentioned, is the callback function the endpoint we just registered uses. Basically, this is where all the “heavy lifting” is done.

Put simply—it checks that “scoreLeft” and “dartsThrown” aren’t empty, works out the darts average using the formula (501-$scoreLeft)/$dartsThrown then returns the result to display to the user.

function darts_calculator($request) {
    if (empty($request['scoreLeft']) && empty($request['dartsThrown'])) {
		return new WP_REST_Response(
      		array(
        		'status' => '400',
        		'response' => 'Bad request'
    		)
		);
    } else {
        $scoreLeft = (int)sanitize_text_field($request['scoreLeft']);
        $dartsThrown = (int)sanitize_text_field($request['dartsThrown']);
        $dartsAverage = (501-$scoreLeft)/$dartsThrown;
        if(is_float($dartsAverage)) {
		$dartsAverage = number_format($dartsAverage,2);
	} else {
		$dartsAverage = number_format($dartsAverage);
	}
	$response_message = "You darts average is ".$dartsAverage;
	return new WP_REST_Response(
      		array(
        		'status' => '200',
        		'response' => $response_message
    		)
	);
    }
}

Hopefully that was all fairly easy to follow—like most things, it looks a lot more complicated than it is.

With that basic run-down of what the various parts of this file do out of the way, you can grab the whole thing in it’s entirety below:

plugin.php

<?php
/**
* Plugin Name: Dart Calculator Demo
* Plugin URI: https://www.duinobit.com
* Description: WPEagle's dart calculator rebuilt using WP REST API
* Version: 1.0
**/

function darts_calculator_script_and_style() {
    wp_register_script( 'darts_calculator_js',plugins_url( '/js/darts_calculator.js', __FILE__ ), '', '', true );
    wp_register_style( 'darts_calculator_css',plugins_url( 'css/darts_calculator.css', __FILE__ ));
}
add_action( 'wp_enqueue_scripts', 'darts_calculator_script_and_style');

function darts_calculator_shortcode() {
    if (!is_admin()) {
        ob_start();
        require plugin_dir_path( __FILE__ ).'html/darts_calculator.html';
        wp_enqueue_script('darts_calculator_js');
		wp_enqueue_style('darts_calculator_css');
        return ob_get_clean();
    }
}
add_shortcode('darts_calculator', 'darts_calculator_shortcode');

function darts_calculator_route() {
    register_rest_route('dartsCalculator', 'v1', [
        'methods'  => WP_REST_SERVER::READABLE,
        'callback' => 'darts_calculator'
    ]);
}
add_action('rest_api_init', 'darts_calculator_route');

function darts_calculator($request) {
    if (empty($request['scoreLeft']) && empty($request['dartsThrown'])) {
		return new WP_REST_Response(
      		array(
        		'status' => '400',
        		'response' => 'Bad request'
    		)
		);
    } else {
        $scoreLeft = (int)sanitize_text_field($request['scoreLeft']);
        $dartsThrown = (int)sanitize_text_field($request['dartsThrown']);
        $dartsAverage = (501-$scoreLeft)/$dartsThrown;
        if($dartsAverage < 60) {
            $playerLevel = "a below average";
        } elseif($dartsAverage >= 60 && $dartsAverage <= 80) {
            $playerLevel = "an average";
        } elseif($dartsAverage > 80) {
            $playerLevel = "a good";
        }
	if(is_float($dartsAverage)) {
		$dartsAverage = number_format($dartsAverage,2);
	} else {
		$dartsAverage = number_format($dartsAverage);
	}
	$response_message = "You darts average is ".$dartsAverage.". You're ".$playerLevel." darts player.";
	return new WP_REST_Response(
      		array(
        		'status' => '200',
        		'response' => $response_message
    		)
         );
    }
}

darts_calculator.js

This is the JS used for the calculator, which does a little bit of super basic validation on submit—just checking that both “scoreLeft” and “dartsThrown” are set—then makes the request to the endpoint using fetch and handles the response, outputting it to the “notice” div.

darts_calculator.js

const form = document.querySelector('form#dartsCalculator')
const notice = form.querySelector('div#notice')
const scoreLeft = form.querySelector('input#scoreLeft')
const dartsThrown = form.querySelector('input#dartsThrown')

function formSubmit(e) {
    resetNotice()
    validate()
    e.preventDefault()
}

function validate() {
    if(scoreLeft.value && dartsThrown.value) {
        request()
    } else {
        notice.textContent = "Form incomplete. Please check and try again."
    }
}

function request() {
    fetch(`https://www.duinobit.com/wp-json/dartsCalculator/v1?scoreLeft=${scoreLeft.value}&dartsThrown=${dartsThrown.value}`).then(function(response) {
        return response.json()
    }).then(function(data){
        if(data.status == "200") {
            notice.textContent = data.response
        } else {
            notice.textContent = "Something went wrong. Please try again."
        }
        notice.textContent = data.response
    }).catch(function (err) {
        console.warn('Something went wrong.', err)
    })
}

function resetNotice() {
    notice.textContent = ""
}

form.addEventListener('submit', formSubmit);

darts_calculator.html

This is just the html form that’s rendered when the shortcode is used—nothing fancy.

The only thing that I would says is that I added some JS—much of which came from this post on Stackoverflow—to help prevent the user inputting incorrect data into each field, which were mostly missing from WP Eagle’s example.

These restrict the input fields to whole numbers and stops the “scoreLeft” from being set higher than “501”.

darts_calculator.html

<form id="dartsCalculator">
    <div>
        <label for="scoreLeft">Score left</label><br>
        <input id="scoreLeft" type="number" step="1" min="0" max="501" onkeydown="if(event.key==='.'){event.preventDefault();}" onpaste="let pasteData = event.clipboardData.getData('text'); if(pasteData){pasteData.replace(/[^0-9]*/g,'');}" onkeyup="if(this.value > 501) this.value = 501;">
    </div>
    <div>
        <label for="dartsThrown">Darts thrown</label><br>
        <input id="dartsThrown" type="number" step="1" min="0" onkeydown="if(event.key==='.'){event.preventDefault();}" onpaste="let pasteData = event.clipboardData.getData('text'); if(pasteData){pasteData.replace(/[^0-9]*/g,'');}">
    </div>
    <div>
        <div id="notice"></div>
    </div>
    <div>
        <input type="submit" value="Calculate">
    </div>
</form>

darts_calculator.css

This is just some super basic CSS to style the form.

darts_calculator.css

form#dartsCalculator, form#dartsCalculator > div, form#dartsCalculator > div > input {
    width: 100%;
}

form#dartsCalculator > div {
    padding-bottom: 10px;
}

form#dartsCalculator > div > label {
    font-weight: 700;
}

form#dartsCalculator > div > div#notice {
    text-align: center;
}

How to set it up

dart_calculator
│   plugin.php
└───css
│   	darts_calculator.css
└───html
│   	darts_calculator.html
└───js
	darts_calculator.js

You’ll also need to update the endpoint route using your own website URL—and reflect any changes you made when the route is registered in plugin.php.

I’ve included the relevant snippet from the darts_calculator.js below for reference:

darts_calculator.js

function request() {
    fetch(`https://www.duinobit.com/wp-json/dartsCalculator/v1?scoreLeft=${scoreLeft.value}&dartsThrown=${dartsThrown.value}`).then(function(response) {
        return response.json()
    }).then(function(data){
        if(data.status == "200") {
            notice.textContent = data.response
        } else {
            notice.textContent = "Something went wrong. Please try again."
        }
        notice.textContent = data.response
    }).catch(function (err) {
        console.warn('Something went wrong.', err)
    })
}

After that, put everything into a ZIP archive, install and activate it on your WordPress site, and then use the shortcode wherever you want to include the calculator—the shortcode for this example calculator is given below again for reference:

[darts_calculator /]

That’s it—not too complicated really.

Summing it up

Well that’s it, a basic example of how you can use the WordPress REST API to make your own calculators. While the example is pretty simple, it can be extended and built upon with a little effort—or even used as a basis for completely different calculators you may want to build for your own site.

Going this way can also be useful for other reasons. You could make a calculator built this way embeddable on other websites, serve better targeted content based on it’s result, or capture the responses to create content based around use inputs—which are just a handful of examples.

I expect I’ll create content about how to do some of these in the future, as creating tools and calculators is something I’m a big fan of and intend to focus heavily on over the next year—as it’s far easier in my view to create link worthy assets in code than to crank out long-form article after long-form article.

If you made it this far, thanks for reading! And if you have any questions or need any help getting the example given here working, feel free to drop me a comment below and I’ll do my best to answer these or give you hand getting this working for you.

Share this:

Leave a Comment