Responsive Numeric Keypad With HTML Javascript (Free Download)

Welcome to a tutorial on how to create an on-screen numeric keypad using only pure Javascript. Yes, HTML has gotten a lot more powerful and convenient these days. We can define a field that only accepts numbers, but there is just one problem with it…

It will only display an on-screen keypad with mobile devices, and we cannot customize it. So here it is, this guide will walk you through a simple and lightweight custom numeric keypad – Read on!

 

 

TABLE OF CONTENTS

 

JAVASCRIPT NUMPAD

Let us now move into a short demo of the numpad, and also on the detail of how it works.

 

NUMERIC KEYPAD DEMO (HOW TO USE)

1-numpad.html
<!-- (A) LOAD JS + CSS -->
<link rel="stylesheet" href="numpad.css">
<script src="numpad.js"></script>
 
<!-- (B) INPUT FIELDS -->
Field A: <input type="text" id="demoA">
Field B: <textarea id="demoB"></textarea>
 
<!-- (C) ATTACH NUMPAD -->
<script>
window.addEventListener("load", () => {
  // (C1) BASIC NUMPAD
  numpad.attach({ target: document.getElementById("demoA") });
 
  // (C2) WITH ALL POSSIBLE OPTIONS
  numpad.attach({
    target: document.getElementById("demoB"),
    maxDig : 6, // max digits (whole number), default 10
    maxDec : 0, // to disable decimal places, default 2
    onselect : num => alert(num), // call this on select
    oncancel : () => alert("DEMO B canceled.") // call this on cancel
  });
});
</script>

Field A:

Field B:

For you guys who don’t want to read the entire tutorial and just want to use this as a “plugin”:

  1. Simply include the CSS and Javascript files in your own project.
  2. Define the <input> or <textarea> fields.
  3. On window load, use numpad.attach() attach the numpad to the fields.
    • target Required, the HTML field to tie the numpad to.
    • maxDig Optional, the maximum of digits for whole numbers.
    • maxDec Optional, the maximum of digits for decimals.
    • onselect Optional, function to call when the user hits “OK”.
    • oncancel Optional, function to call when the user hits “CANCEL”.

 

PART 1) INITIALIZE NUMPAD (ATTACH HTML)

2-numpad.js
var numpad = {
  // (A) PROPERTIES
  // (A1) HTML ELEMENTS
  hWrap: null, // numpad wrapper container
  hDisplay: null, // number display
  now : null, // current active instance
 
  // (B) INIT - CREATE NUMPAD HTML
  init: () => {
    // (B1) NUMPAD WRAPPER
    numpad.hWrap = document.createElement("div");
    numpad.hWrap.id = "numWrap";
    numpad.hWrap.innerHTML = `<div id="numPad">
      <input type="text" id="numDisplay" disabled="true" value="0">
      <div id="numBWrap"></div>
    </div>`;
    document.body.appendChild(numpad.hWrap);
    numpad.hDisplay = document.getElementById("numDisplay");
 
    // (B2) ATTACH BUTTONS
    let hbWrap = document.getElementById("numBWrap"),
    buttonator = (txt, css, fn) => {
      let button = document.createElement("div");
      button.innerHTML = txt;
      button.classList.add(css);
      button.onclick = fn;
      hbWrap.appendChild(button);
    };
    for (let i=7; i<=9; i++) { buttonator(i, "num", () => numpad.digit(i)); }
    buttonator("&#10502;", "del", numpad.delete);
    for (let i=4; i<=6; i++) { buttonator(i, "num", () => numpad.digit(i)); }
    buttonator("C", "clr", numpad.reset);
    for (let i=1; i<=3; i++) { buttonator(i, "num", () => numpad.digit(i)); }
    buttonator("&#10006;", "cx", () => numpad.hide(1));
    buttonator(0, "zero", () => numpad.digit(0));
    buttonator(".", "dot", numpad.dot);
    buttonator("&#10004;", "ok", numpad.select);
  },
  // ...
};
window.addEventListener("DOMContentLoaded", numpad.init);

numpad.init() is the first thing that gets called on page load, and all it does is create the Numpad HTML. We will go through the layout below, but yes, there is only one copy of Numpad shared between all the input fields.

 

 

PART 2) BUTTON ACTIONS

2-numpad.js
// (C) BUTTON ACTIONS
// (C1) NUMBER (0 TO 9)
digit: num => {
  // (C1-1) CURRENT VALUE
  let v = numpad.hDisplay.value;
 
  // (C1-2) WHOLE NUMBER (NO DECIMAL POINT)
  if (v.indexOf(".") == -1) { if (v.length < numpad.now.maxDig) {
    if (v=="0") { numpad.hDisplay.value = num; }
    else { numpad.hDisplay.value += num; }
  }}
 
  // (C1-3) DECIMAL POINT
  else { if (v.split(".")[1].length < numpad.now.maxDec) {
    numpad.hDisplay.value += num;
  }}
},
 
// (C2) ADD DECIMAL POINT
dot: () => { if (numpad.hDisplay.value.indexOf(".") == -1) {
  if (numpad.hDisplay.value=="0") { numpad.hDisplay.value = "0."; }
  else { numpad.hDisplay.value += "."; }
}},
 
// (C3) BACKSPACE
delete: () => {
  var length = numpad.hDisplay.value.length;
  if (length == 1) { numpad.hDisplay.value = 0; }
  else { numpad.hDisplay.value = numpad.hDisplay.value.substring(0, length - 1); }
},
 
// (C4) CLEAR ALL
reset: () => numpad.hDisplay.value = "0",
 
// (C5) OK - SET VALUE
select: () => {
  let v = numpad.hDisplay.value;
  numpad.now.target.value = v;
  numpad.hide();
  if (numpad.now.onselect) { numpad.now.onselect(v); }
},

Not going to explain line-by-line, but these should be pretty self-explanatory – Handle the button clicks and update the value accordingly.

 

 

PART 3) SHOW/HIDE NUMPAD

2-numpad.js
// (D) SHOW NUMPAD
show: instance => {
  // (D1) SET CURRENT INSTANCE + DISPLAY VALUE
  numpad.now = instance;
  let cv = instance.target.value;
  if (cv=="" || isNaN(cv)) { cv = "0"; }
  numpad.hDisplay.value = cv;
 
  // (D2) SET DECIMAL
  if (instance.maxDec==0) { numpad.hWrap.classList.add("noDec"); }
  else { numpad.hWrap.classList.remove("noDec") }
 
  // (D3) SHOW NUMPAD
  numpad.hWrap.classList.add("open");
},
 
// (E) HIDE NUMPAD
hide: manual => {
  if (manual && numpad.now.oncancel) { numpad.now.oncancel(); }
  numpad.hWrap.classList.remove("open");
}

Don’t think this needs a lot of explanation.

  • numpad.show() Sets the selected instance and show the numpad.
  • numpad.hide() Close the numpad.

 

PART 4) ATTACH NUMPAD

2-numpad.js
// (F) ATTACH NUMPAD TO INPUT FIELD
// target: required, target field.
// maxDig: optional, maximum number of digits, default 10.
// maxDec: optional, maximum number of decimal places, default 2.
// onselect: optional, function to call after selecting number.
// oncancel: optional, function to call after canceling.
attach: instance => {
  // (F1) DEFAULT OPTIONS
  if (instance.maxDig === undefined) { instance.maxDig = 10; }
  if (instance.maxDec === undefined) { instance.maxDec = 2; }
 
  // (F2) GET + SET TARGET OPTIONS
  instance.target.readOnly = true; // prevent onscreen keyboard
  instance.target.addEventListener("click", () => numpad.show(instance));
}

You have already seen this one in the above “quickstart demo”. We pretty much set the default options, add “read-only” on the target input field, and click on it to open the numpad.

 

 

NUMPAD HTML

Wondering what the complete keypad looks like exactly? Here we go:

<div id="numWrap"><div id="numPad">
  <input id="numDisplay" type="text" disabled="">
  <div id="numBWrap" >
    <!-- FIRST ROW -->
    <div class="num">7</div> <div class="num">8</div> <div class="num">9</div> <div class="del">⤆</div>
 
    <!-- SECOND ROW -->
    <div class="num">4</div> <div class="num">5</div> <div class="num">6</div> <div class="clr">C</div>
 
    <!-- THIRD ROW -->
    <div class="num">1</div> <div class="num">2</div> <div class="num">3</div> <div class="cx">X</div>
 
    <!-- FORTH ROW -->
    <div class="zero">0</div> <div class="dot">.</div> <div class="ok">✔</div>
  <div>
</div></div>

 

DOWNLOAD & NOTES

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

EXAMPLE CODE DOWNLOAD

Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

EXTRA BITS & LINKS

That’s all for this guide, and here is a small section on some extras that may be useful to you.

 

CHANGE BUTTON LAYOUT OR ADD CUSTOM BUTTONS

  • To change the layout, simply reshuffle numpad.js section (B2).
  • If you don’t want 4 buttons per row, update CSS sections (D) and (F).

If you want buttons for funny characters like # - *, that will be a little more challenging.

  • Append a new function in section (C) to handle the button press. For example, hash : () => numpad.hDisplay.value += "#".
  • Then change section (B2) in the Javascript to add your “custom button”. For example, buttonator("#", "hash", numpad.hash).
  • Lastly, update the CSS button layout where applicable.

 

 

CUSTOM VALUE SETTINGS & CHECKS

  • Why are broken decimals such as 123. allowed? Why is it not removed automatically?
  • Why is there no feature to pad with trailing zeroes?
  • Pad with leading zeroes?
  • Automatic thousand separators?
  • Add currency symbols?
  • Isn’t 123.00 the same as 123? Why not automatically remove the decimals?
  • Automatically add a trailing .00 if decimals are not defined.
  • Use , instead of ..

Yep. I figured that this list can go on forever. So if you need “specific settings”, please modify the script by yourself… It’s mostly in section (C5).

 

KEYBOARD “ADDON”

Add this function:

listen: e => {
  if (e.key === "0") { numpad.digit(0); }
  if (e.key === "1") { numpad.digit(1); }
  if (e.key === "2") { numpad.digit(2); }
  if (e.key === "3") { numpad.digit(3); }
  if (e.key === "4") { numpad.digit(4); }
  if (e.key === "5") { numpad.digit(5); }
  if (e.key === "6") { numpad.digit(6); }
  if (e.key === "7") { numpad.digit(7); }
  if (e.key === "8") { numpad.digit(8); }
  if (e.key === "9") { numpad.digit(9); }
  if (e.key === "Backspace") { numpad.delete(); }
  if (e.key === "Enter") { numpad.select(); }
  if (e.key === "Escape") { numpad.hide(); }
},

Modify show/hide:

show: instance => {
  window.addEventListener("keydown", numpad.listen);
  ...
},
hide: manual => {
  window.removeEventListener("keydown", numpad.listen);
  ...
}

I did not add this in, as mobile devices and touch screens are literally more common than keyboards now…

 

COMPATIBILITY CHECKS

Works well across all modern browsers.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

37 thoughts on “Responsive Numeric Keypad With HTML Javascript (Free Download)”

  1. as a novice I am struggling with how to pass through a form input.
    This keypad is perfect for what I need but I can’t figure out how to get the entered value into $_POST

    what goes in the value?
    ps love the keyboard but know nothing about js

  2. Hello, thanks for this code! I added the below snippet to add keyboard functionality, in case you wanted to copy it in to your source.

    window.addEventListener('keydown', event => {
        if (event.key === "0") { numpad.digit(0); }
        if (event.key === "1") { numpad.digit(1); }
        if (event.key === "2") { numpad.digit(2); }
        if (event.key === "3") { numpad.digit(3); }
        if (event.key === "4") { numpad.digit(4); }
        if (event.key === "5") { numpad.digit(5); }
        if (event.key === "6") { numpad.digit(6); }
        if (event.key === "7") { numpad.digit(7); }
        if (event.key === "8") { numpad.digit(8); }
        if (event.key === "9") { numpad.digit(9); }
        if (event.key === "Backspace") { numpad.delete(); }
        if (event.key === "Enter") { numpad.select(); }
    })
    1. Thanks for sharing, it is a better idea to attach the keydown listener only when the keypad is open – May add this in the next update.

Leave a Comment

Your email address will not be published. Required fields are marked *