Software, your way.
burger menu icon
WillMaster

WillMaster > LibraryManaging Website Forms

FREE! Coding tips, tricks, and treasures.

Possibilities weekly ezine

Get the weekly email website developers read:

 

Your email address

name@example.com
YES! Send Possibilities every week!

Payment Amount Selector

Recently, I've received a couple opportunities to create payment forms where an amount is selected by tapping on it.

One was for how many items the person is ordering. The other was for how much money the person is contributing to the website.

Both use similar code. The amount being contributed contains currency formatting code that the number of items selection does not.

I'll provide code for selecting a contribution amount.

Here is an illustration. (When implementing for currencies other than USD, AUD, or other Dollar currency, replace "$" with the correct currency symbol.)

Select Amount

$10
$20
$50
$100
$250
$500
$1000
Other

Payment amount: $

Tapping on an amount will fill in the "Payment amount" field below the selection boxes. The field is read-only so it can't be changed by the user.

Tapping the "Other" selection box allows an amount to be typed in. This is what gives the selector more than just a simple "tap to select" functionality.

As the "Other" selection box is first tapped, the "Payment amount" field is filled with "(tap to update)".

After the user types in an amount and taps on "(tap to update)" (or taps anywhere else on the page), the "Payment amount" field updates with whatever amount greater than zero is specified in the "Other" selection box.

Implementing the Amount Selector

The code that enables the illustration is provided here.

It is not simple. But I'll try to explain it well enough so it seems that way.

Let's first do the CSS, selection boxes, and "Payment amount" field. Later, we'll do the JavaScript.

The source code is below. Implementation notes follow.

<!-- CSS declarations area. -->
<style>
.amount-box {
    outline:none; 
    float:left; 
    width:150px; 
    padding:10px 0 8px 0;
    font-size:3em;
    border:1px solid blue; 
    border-radius:5px;
    text-align:center; 
    margin:0 6px 6px 0;
    background-color:skyblue;
    cursor:pointer;
    }
</style>

<!-- Amount functionality container. -->
<div style="max-width:470px; margin:0 auto;">

<!-- The selection boxes area. -->
<h3 style="margin-bottom:1px;">Select Amount</h3>
<div onclick="IDtapped('amount10')" id="amount10" class="amount-box" style="outline:none;">$10</div> 
<div onclick="IDtapped('amount20')" id="amount20" class="amount-box" style="outline:none;">$20</div> 
<div onclick="IDtapped('amount50')" id="amount50" class="amount-box" style="outline:none;">$50</div> 
<div onclick="IDtapped('amount100')" id="amount100" class="amount-box" style="outline:none;">$100</div> 
<div onclick="IDtapped('amount250')" id="amount250" class="amount-box" style="outline:none;">$250</div> 
<div onclick="IDtapped('amount500')" id="amount500" class="amount-box" style="outline:none;">$500</div> 
<div onclick="IDtapped('amount1000')" id="amount1000" class="amount-box" style="outline:none;">$1000</div> 
<div onclick="IDtapped('amountOther')" id="amountOther" class="amount-box" style="outline:none;" 
     onblur="UpdateAmount()" onkeyup="ConformAmount(true)" contenteditable="true">Other</div> 
<div style="clear:left;"></div>

<!-- "Payment amount" area. -->
<p>
Payment amount: $<input type="text" 
                        id="payment-amount" 
                        name="amount" 
                        readonly="readonly"
                        style="cursor:pointer; width:125px; border:none;">
</p>

</div>
<!-- End: Amount functionality container. -->

Implementation Notes —

CSS Declarations for the Selection Boxes

At the top of the above code is the CSS rule for the selection boxes. They may be modified as needed for your design preferences. It is recommended to keep the cursor:pointer; declaration so desktop/laptop computers see the pointer mouse cursor when the mouse hovers over a selection box.

The green and red declarations are referred to in the The Selection Boxes section below.

You'll see that the CSS layout is float:left;. I did it that way because it is one of the easiest width-responsive layouts and works for many web page designs. You may wish to do a grid or use flex declarations. Or some other method.

In other words, use whatever layout is desired for your implementation and update the CSS declarations accordingly.

The Selection Boxes

Each selection box has onclick, id, class, and style attributes. The "Other" selection box, where a different amount can be typed in, also has onblur and contenteditable attributes. The attributes are addressed below.

The onclick and id attributes:

The onclick attribute has a parameter. The parameter needs to be identical to the id attribute value. In the code above, the parameter and id value are colored blue.

The class attribute:

The class attribute has the same name as the CSS rule in the CSS declarations area near the top of the illustration source code. In the code above and in the CSS style declaration, the class name is amount-box.

The style attribute:

The style attribute must contain outline:none; as part or all of its value. Additional inline styles may be added so long as outline:none; remains as part of the style attribute value.

The onblur attribute:

Only the "Other" selection box contains an onblur attribute. It is not color coded in the above code, but it is bolded. The entire attribute is onblur="UpdateAmount()" and causes the JavaScript function UpdateAmount() to run when the box goes out of focus.

The onkeyup attribute:

Only the "Other" selection box contains an onkeyup attribute. It is not color coded in the above code, but it is bolded. The entire attribute is onkeyup="ConformAmount(true)" and causes the JavaScript function ConformAmount() to run when a key is released.

The contenteditable attribute:

Only the "Other" selection box contains a contenteditable attribute. It is not color coded in the above code, but it is bolded. The entire attribute is contenteditable="true" and is the attribute that allows you to edit the content of a div.

Modifying the Selection Boxes

Selection boxes may be added and removed.

Selection box id values may be modified with corresponding modifications for the UpdateAmount() function call parameters at the onclick attribute. The class name may be changed if it is also changed for the CSS rule where the CSS declaration is declared.

The outline:none; value is required in the style, although other CSS declarations may be added.

For the "Other" selection box, the onblur, onkeyup, and contenteditable attributes are required.

Other than those considerations, modify the section boxes and their content as you wish.

The "Payment amount" Field

After someone selects an amount or types an amount into the "Other" selection box, the "Payment amount" field is filled in with the selected or typed amount.

The "Payment amount" field is a regular form field made so it can't be edited. It has a number of special attributes and is initially assigned a special value.

The id attribute:

The JavaScript requires the id attribute so it knows where to publish the amount that was selected. If the payment-amount is changed to something else, a corresponding change needs to be made in customization section of the JavaScript.

The name attribute:

The code contains a name attribute as a placeholder for you to assign the form field name you need for your implementation. The name attribute's presence or absence doesn't affect the live illustration on this page.

The readonly attribute:

The readonly="readonly" attribute is required to make the "Payment amount" field unchangeable for the user.

In HTML5, readonly (no value) is preferred but readonly="readonly" is allowed. Other HTML versions require a value for the readonly attribute, so readonly="readonly" is used in the above source code.

The style attribute:

The style attribute is optional. A cursor:pointer; definition may make it more intuitive when the mouse cursor changes to a pointer. (The "(tap to update)" text appears when the "Other" selection box is tapped on.)

Modifying the "Payment amount" Field

For the "Payment amount" Field, the id and readonly attributes are required.

Other than those considerations, modify the "Payment amount" field as you wish.

Implementing the JavaScript

The JavaScript needs to be put anywhere below the amount selection area. Above the cancel </body> tag should work.

The source code is below. Implementation notes follow.

<script>
/*
   Amount Selector
   Version 1.0
   August 20, 2018

   Will Bontrager Software LLC
   https://www.willmaster.com/
   Copyright 2018 Will Bontrager Software LLC

   This software is provided "AS IS," without any warranty of any kind, without even 
   any implied warranty such as merchantability or fitness for a particular purpose. 
*/

/* Customizations */
// Four places.

// Place 1.
// Specify styling differences for the amount area that is selected. 
// Must always at least specify an outline declaration -- color may be transparent.
var SelectedArea = "outline:1px solid transparent; background-color:white; color:#0099cc";

// Place 2.
// Specify styling differences for the amount area that is not selected. 
// Must always at least specify outline:none.
var NotSelectedArea = "outline:none; background-color:#87ceeb; color:black;";

// Place 3.
// Within the Array parameters, specify the id values of each amount selection box -- including the id value of the "Other" selection box.
var IDvalues = Array( "amount10", "amount20", "amount50", "amount100", "amount250", "amount500", "amount1000", "amountOther" );

// Place 4.
// Specify the id value of the editable selection box (should also be listed in the IDvalues Array() parameters).
var IDofEditableField = "amountOther";

// Place 5.
// Optionally, specify a currency symbol to be prepended and/or appended to the amount typed into the editable field.
var PrependSymbolToEditableAmount = "$";
var AppendSymbolToEditableAmount = "";

// Place 6.
// Specify the id value of the "Payment amount" field where the selected amount is published.
var AmountFieldID = "payment-amount";

/* End of customization. */

function PowerhouseStyleChange(idvalue,style)
{
    var id = document.getElementById(idvalue);
    var ta = style.split(/\s*;\s*/);
    for( var i=0; i<ta.length; i++ )
    {
        var tta = ta[i].split(':',2);
        var ttaa = tta[0].split('-');
        if( ttaa.length > 1 )
        {
            for( var ii=1; ii<ttaa.length; ii++ ) { ttaa[ii] = ttaa[ii].charAt(0).toUpperCase() + ttaa[ii].slice(1); }
        }
        tta[0] = ttaa.join('');
        id.style[tta[0]] = tta[1];
    }
} // function PowerhouseStyleChange()

function DoStyleChange(id,style)
{
    var styles = style.split(/; */);
    for( var i=0; i< styles.length; i++ ) 
    {
        if( styles[i].match(/:/) ) { PowerhouseStyleChange(id,styles[i]); }
    }
} // function DoStyleChange()

function AttachCurrencySymbols(n)
{
    if( PrependSymbolToEditableAmount.length ) { n = PrependSymbolToEditableAmount + n; }
    if( AppendSymbolToEditableAmount.length ) { n = n + AppendSymbolToEditableAmount; }
    return n;
} // function AttachCurrencySymbols()

function ConformActualAmountInDiv(d)
{
    d.innerHTML = d.innerHTML.replace(/[^\.\,\d]/g,"");
    if( d.innerHTML.length < 1 ) { d.innerHTML = '&nbsp;'; }
} // function ConformActualAmountInDiv()

function ConformAmount(removeAmountInField)
{
    var editdiv = document.getElementById(IDofEditableField);
    ConformActualAmountInDiv(editdiv);
    var sel = window.getSelection();
    var range = sel.getRangeAt(0);
    range.setStart(editdiv,1);
    range.collapse(false);
    sel.removeAllRanges();
    sel.addRange(range);
    if( removeAmountInField ) { document.getElementById(AmountFieldID).value = '(tap to update)'; }
} // function ConformAmount()

function IDtapped(amount)
{
    for( var i=0; i<IDvalues.length; i++ ) { DoStyleChange(IDvalues[i],NotSelectedArea); }
    DoStyleChange(amount,SelectedArea);
    var d = document.getElementById(IDofEditableField);
    if( amount == IDofEditableField ) { d.innerHTML = "&nbsp;"; }
    else { d.innerHTML = "Other"; }
    UpdateAmount();
} // function IDtapped()

function UpdateAmount()
{
    var amount = 0.0;
    var hasamount = false;
    var field = document.getElementById(AmountFieldID);
    var editdiv = document.getElementById(IDofEditableField);
    for( var i=0; i<IDvalues.length; i++ )
    {
        var d = document.getElementById(IDvalues[i]);
        if( ! d.style.outline.match(/none/) )
        {
            hasamount = true;
            amount = d.innerHTML;
        }
        if( hasamount ) { amount = amount.replace(/[^\.\d\-]/g,''); }
        if( hasamount && amount > 0.0 ) { field.value = CurrencyFormat(amount); }
        else
        {
            if( editdiv.style.outline.match(/none/) ) { field.value = '(select above)'; }
            else { field.value = '(tap to update)'; }
        }
        if( hasamount && amount > 0.0 && IDvalues[i] == IDofEditableField )
        {
            ConformActualAmountInDiv(editdiv);
            if( editdiv.innerHTML.match(/\d/) )
            {
                var amd = CurrencyFormat(editdiv.innerHTML);
                amd = amd.replace(/\.00$/,"");
                editdiv.innerHTML = AttachCurrencySymbols(amd);
            }
            else { editdiv.innerHTML = 'Other'; }
        }
    }
} // function UpdateAmount()

function CurrencyFormat(number)
{
    // To customize currency formatting in this function, see https://www.willmaster.com/library/tools/currency-formatting.php
    var decimalplaces = 2;
    var decimalcharacter = ".";
    var thousandseparater = ",";
    number = parseFloat(number);
    var sign = number < 0 ? "-" : "";
    var formatted = new String(number.toFixed(decimalplaces));
    if( decimalcharacter.length && decimalcharacter != "." ) { formatted = formatted.replace(/\./,decimalcharacter); }
    var integer = "";
    var fraction = "";
    var strnumber = new String(formatted);
    var dotpos = decimalcharacter.length ? strnumber.indexOf(decimalcharacter) : -1;
    if( dotpos > -1 )
    {
        if( dotpos ) { integer = strnumber.substr(0,dotpos); }
        fraction = strnumber.substr(dotpos+1);
    }
    else { integer = strnumber; }
    if( integer ) { integer = String(Math.abs(integer)); }
    while( fraction.length < decimalplaces ) { fraction += "0"; }
    temparray = new Array();
    while( integer.length > 3 )
    {
        temparray.unshift(integer.substr(-3));
        integer = integer.substr(0,integer.length-3);
    }
    temparray.unshift(integer);
    integer = temparray.join(thousandseparater);
    return sign + integer + decimalcharacter + fraction;
} // function CurrencyFormat()

function DelayedConformAmount()
{
    ConformAmount(false);
    UpdateAmount();
} // function DelayedConformAmount()

window.addEventListener('keydown', function(e)
{
    if(e.keyCode==13 || e.keyCode==10)
    {
        ConformAmount(false);
        setTimeout(DelayedConformAmount,500);
    }
});
UpdateAmount();
</script>

Implementation Notes —

The SelectedArea Variable

Specify the selection box style that is different when it is selected than when it is not selected. There must always be an outline specification (color may be transparent). Any other styles are optional.

The NotSelectedArea Variable

Specify the selection box style that is different when it is not selected than when it is selected. There must always be have an outline:none; specification. Any other styles are optional.

The IDvalues Variable

Within the Array parameters, specify the id values of each amount selection box — including the id value of the "Other" selection box.

The IDofEditableField Variable

Specify the id value of the "Other" selection box.

The PrependSymbolToEditableAmount Variable and the AppendSymbolToEditableAmount Variable

When the "Other" section box is edited with an amount, a currency symbol or other character or series of characters may be prepended or appended to the typed amount. Specify symbols or characters you need. Otherwise, leave the values blank.

The AmountFieldID Variable

Specify the id value of the "Payment amount" field where the selected amount is published.

Using It

I realize there is a lot of techy stuff involved for implementing the amount selector. My intent was to make it as clear as I could.

The "Payment amount" field is the form field where your payment processing software can pick up the amount that was selected or typed in. Change the field's name attribute as necessary.

If you wish to use this JavaScript for a number-of-items selection boxes instead of payment-amount, remove calls to the JavaScript CurrencyFormat() function. There are likely to be some other tweaking things, depending on exactly what you want to do, but removing calls to CurrencyFormat() is likely to be the largest conversion step.

(This article first appeared with an issue of the Possibilities newsletter.)

Will Bontrager

Was this article helpful to you?
(anonymous form)

Support This Website

Some of our support is from people like you who see the value of all that's offered for FREE at this website.

"Yes, let me contribute."

Amount (USD):

Tap to Choose
Contribution
Method

All information in WillMaster Library articles is presented AS-IS.

We only suggest and recommend what we believe is of value. As remuneration for the time and research involved to provide quality links, we generally use affiliate links when we can. Whenever we link to something not our own, you should assume they are affiliate links or that we benefit in some way.

How Can We Help You? balloons
How Can We Help You?
bullet Custom Programming
bullet Ready-Made Software
bullet Technical Support
bullet Possibilities Newsletter
bullet Website "How-To" Info
bullet Useful Information List

© 1998-2001 William and Mari Bontrager
© 2001-2011 Bontrager Connection, LLC
© 2011-2024 Will Bontrager Software LLC