Monday, June 8, 2020

Personalize Radio Buttons

Hello all,

When we're creating a webpage, we first put the skeleton of the page with HTML, then add some shiny skin with CSS, and finally add some muscles with JS.

We can add styles (skin) to every HTML element (bones of the skeleton).... except for some form controls. And on this post I'm going to discuss how to sort it out for the radio button.

First let's get to know the radio button. It's an input element with the the type "radio". Usually we add a name attribute so only 1 radio button is checked at any given time, a value attribute to be read by the JS and is usually paired with a label element.
<div>
    <input type="radio" name="groupName" value="option1>
    <label for="option1">Option 1</label>
</div>
<div>
    <input type="radio" name="groupName" value="option2">
    <label for="option2">Option 2</label>
</div>

And we will get the following output:


Now the styling.
We can't add stylings to the radio buttons and we don't want to create from scratch some new radio buttons (see why at the bottom of the post).

The hacky way forward is:
- to create a new element that we can edit, like a <span>;
- hide the radio button element; and
- wrap everything on the label, so the radio functionality persists and is triggered whenever we click on the label.

So, it will look like this:

HTML
<label for="option1" class="container">option1
<input type="radio" name="groupName" id="option1">
<span class="checkmark"></span>
</label>
<label for="option2" class="container">option2
<input type="radio" name="groupName" id="option2">
<span class="checkmark"></span>
</label>
For the CSS, the bulk of the work will be on styling on the checkmark for the different situations, like when it's checked, not checked, and being hovered on:

/* Customize the label (the container) */
.container {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
user-select: none;
}

/* Hide the browser's default radio button */
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}

/* On mouse-over, add a grey background color */
.container:hover input~.checkmark {
background-color: #bbb;
}

/* When the radio button is checked, add a blue background */
.container input:checked~.checkmark {
background-color: #38f;
}


/* Create a custom radio button */
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 24px;
width: 32px;
background-color: #ccc;
border-radius: 12px;
}

/* Create the indicator (the dot/circle - hidden when not checked) */
.checkmark:after {
display: none;
}

/* Show the indicator (dot/circle) when checked */
.container input:checked~.checkmark:after {
content: "";
position: absolute;
display: block;
}

/* Style the indicator (dot/circle) */
.container .checkmark:after {
top: 8px;
left: 11px;
width: 10px;
height: 8px;
border-radius: 5px;
background: #ddd;
}
This will produce an output like this:


It does seem a lot of work (and it is), but it's better than creating a custom component for 2 reasons:
1- It's more accessible. People using a screen reader will more easily understand what's happening, and
2- We don't need to create the JS for this functionality, so less work.

I hope this was helpful and have a great day ;)

Thursday, July 5, 2018

Ajax connection with PHP

When we start programming PHP, there comes a time when people start asking as to do the front-side of the application as well.
So we learn HTML, CSS and some JavaScript (and jQuery). We create great looking webpages with some animations.
But it's not enough: wouldn't it be better if the user would talk back with the server? And so we start delving into AJAX.
Here's a simple example on how it works.

Consider the follow index.php:


<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="ajaxRequest.js"></script>
</head>
<body>
    <select id="animalSelector">
        <?php
            require_once dirname(__FILE__) . '/DAL.php';
            $listAnimals = GetAnimals();
            foreach($listAnimals as $animal){
                $id = $animal['id'];
                $name = $animal['name'];
                echo "<option value=$id>$name</option>";
            }
        ?>
    </select>
    <select id = breedSelector>
        <?php
            require_once dirname(__FILE__) . '/DAL.php';
            $listBreeds = GetBreeds(1);
            foreach($listBreeds as $breed){
                echo "<option>$breed</option>";
            }
        ?>
    </select>
</body>
</html>


On the header it calls for jQuery and an yet to be created Javascript file.
On the body it creates two <select> elements which will be populated via php (theoretically from a database). Both <select> have an id so they can be accessed with our js file.

Our ajaxRequest.js file will wake up whenever the first <select> is changed and will run an ajaxReceiver.php file, in order to update the 2nd <select>.

$(document).ready(function(){
    $('#animalSelector').change(function(){
        var animalId = $('#animalSelector').val();
       
        $.ajax({
            url: 'ajaxReceiver.php',
            type: 'post',
            data: {
                action: 'getBreeds',
                id: animalId,
                XDEBUG_SESSION_START: 'netbeans-xdebug' //allows the code to be debugged with netbeans
            },
            success: function(output){
                $('#breedSelector').html(output);
            },
            error: function(error){
                alert("Error: " + error);
            }
        });
    });
});


Inside the Ajax brackets we define the parameters: url for which file to call, data are the parameters to send, and what to do after receiving a good or bad response.

The ajaxReceiver.php file's responsibility is to receive the ajax request, sanitize parameters, call the necessary functions to get data and to echo it back to the browser.

<?php
$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_SPECIAL_CHARS);
$animalId = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);

if($action == 'getBreeds'){
    require_once dirname(__FILE__) . '/DAL.php';
    $breedList = GetBreeds((int)$animalId);
    $response = "";
    foreach($breedList as $breed){
        $response .= "<option>$breed</option>";
    }
    echo $response;
}
?>


The DAL.php file, standing for Data Access Layer, should connect to a DB to retrieve data. For the simplicity sake, I've just hard coded the data directly.

<?php
    function GetAnimals(){
        $animal1 = array("id"=>1, "name"=> "dog");
        $animal2 = array("id"=>2, "name"=> "cat");
        $animal3 = array("id"=>3, "name"=> "horse");
       
        return array($animal1, $animal2, $animal3);
    }
   
    function GetBreeds($id){
        if($id===1){
            $a = array("German Shepherd", "Golden Retriever", "Dobermann");
            return $a;
        } else if($id===2){
            $a = array("Persian", "Siamese", "Maine Coon");
            return $a;
        } else if($id===3){
            $a = array("Mustang", "Arabian Horse", "Percheron");
            return $a;
        }
    }
?>


There are a ton of add-ons that this process could have, from a loading icon while the request is being processed to validation being handled on the client side.

I'll probably transfer this blog to another server which gives colour to my code.