Responsive Numeric Keypad With HTML Javascript – Free Code 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 even 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!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

TABLE OF CONTENTS

Download & Demo How It Works Useful Bits & Links
The End

 

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

HOW TO USE – QUICKSTART

numpad.html
<!-- (A) LOAD JS + CSS -->
<!-- <link rel="stylesheet" href="numpad-light.css"/> -->
<link rel="stylesheet" href="numpad-dark.css"/>
<script src="numpad.js"></script>
 
<!-- (B) INPUT FIELDS -->
Field A: <input type="text" id="demoA"/>
<br><br>
Field B: <textarea id="demoB"></textarea>
 
<!-- (C) ATTACH NUMPAD -->
<script>
window.addEventListener("load", function(){
  // (C1) BASIC
  numpad.attach({target: document.getElementById("demoA")});
 
  // (C2) ALL OPTIONS
  numpad.attach({
    target: document.getElementById("demoB"),
    max: 10, // MAX 10 DIGITS
    decimal: false, // NO DECIMALS ALLOWED
    onselect : function () { // CALL THIS AFTER SELECTING NUMBER
      alert("DEMO B number set.");
    }
  });
});
</script>

For you guys who don’t want to read the entire 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> fields, and give them an id.
  3. On window load, use the numpad.attach() function to attach the numpad to the input field.

 

 

NUMERIC KEYPAD DEMO

Field A:

Field B:

 

QUICK NOTES

If you spot a bug, please feel free to comment below. I try to answer questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

HOW IT WORKS

With that, let us now move into the details of how the numpad works – This is for you guys who want to do some “deep customizations”.

 

THE JAVASCRIPT

numpad.js
var numpad = {
  // (A) CREATE NUMPAD HTML
  hwrap: null, // numpad wrapper container
  hpad: null, // numpad itself
  hdisplay: null, // number display
  hbwrap: null, // buttons wrapper
  hbuttons: {}, // individual buttons
  init: function(){
    // (A1) WRAPPER
    numpad.hwrap = document.createElement("div");
    numpad.hwrap.id = "numWrap";
 
    // (A2) ENTIRE NUMPAD ITSELF
    numpad.hpad = document.createElement("div");
    numpad.hpad.id = "numPad";
    numpad.hwrap.appendChild(numpad.hpad);
 
    // (A3) DISPLAY
    numpad.hdisplay = document.createElement("input");
    numpad.hdisplay.id = "numDisplay";
    numpad.hdisplay.type = "text";
    numpad.hdisplay.disabled = true;
    numpad.hdisplay.value = "0";
    numpad.hpad.appendChild(numpad.hdisplay);
 
    // (A4) NUMBER BUTTONS
    numpad.hbwrap = document.createElement("div");
    numpad.hbwrap.id = "numBWrap";
    numpad.hpad.appendChild(numpad.hbwrap);

    // (A5) BUTTONS
    let buttonator = function (txt, css, fn) {
      let button = document.createElement("div");
      button.innerHTML = txt;
      button.classList.add(css);
      button.addEventListener("click", fn);
      numpad.hbwrap.appendChild(button);
      numpad.hbuttons[txt] = button;
    };
    // 7 to 9
    for (let i=7; i<=9; i++) { buttonator(i, "num", numpad.digit); }
    // Backspace
    buttonator("&#10502;", "del", numpad.delete);
    // 4 to 6
    for (let i=4; i<=6; i++) { buttonator(i, "num", numpad.digit); }
    // Clear
    buttonator("C", "clr", numpad.reset);
    // 1 to 3
    for (let i=1; i<=3; i++) { buttonator(i, "num", numpad.digit); }
    // Cancel
    buttonator("&#10006;", "cx", numpad.hide);
    // 0
    buttonator(0, "zero", numpad.digit);
    // .
    buttonator(".", "dot", numpad.dot);
    // OK
    buttonator("&#10004;", "ok", numpad.select);
 
    // (A6) ATTACH NUMPAD TO HTML BODY
    document.body.appendChild(numpad.hwrap);
  },
 
  // (B) BUTTON ACTIONS
  // (B1) CURRENTLY SELECTED FIELD + MAX LIMIT
  nowTarget: null, // Current selected input field
  nowMax: 0, // Current max allowed digits
 
  // (B2) NUMBER (0 TO 9)
  digit: function(){
    let current = numpad.hdisplay.value,
        append = this.innerHTML;
    if (current.length < numpad.nowMax) {
      if (current=="0") {
        numpad.hdisplay.value = append;
      } else {
        numpad.hdisplay.value += append;
      }
    }
  },
 
  // (B3) ADD DECIMAL POINT
  dot: function(){
    if (numpad.hdisplay.value.indexOf(".") == -1) {
      if (numpad.hdisplay.value=="0") {
        numpad.hdisplay.value = "0.";
      } else {
        numpad.hdisplay.value += ".";
      }
    }
  },
 
  // (B4) BACKSPACE
  delete: function(){
    var length = numpad.hdisplay.value.length;
    if (length == 1) { numpad.hdisplay.value = 0; }
    else { numpad.hdisplay.value = numpad.hdisplay.value.substring(0, length - 1); }
  },
 
  // (B5) CLEAR ALL
  reset: function(){ numpad.hdisplay.value = "0"; },
 
  // (B6) OK - SET VALUE
  select: function(){
    numpad.nowTarget.value = numpad.hdisplay.value;
    numpad.hide();
    numpad.nowTarget.dispatchEvent(new Event("numpadok"));
  },
 
  // (C) ATTACH NUMPAD TO INPUT FIELD
  attach: function(opt){
  // OPTIONS
  // target: required, target field.
  // max: optional, maximum number of characters. Default 255.
  // decimal: optional, allow decimal? Default true.
  // onselect: optional, function to call after selecting number.
 
    // (C1) DEFAULT OPTIONS
    if (opt.max === undefined) { opt.max = 255; }
    if (opt.decimal === undefined) { opt.decimal = true; }
 
    // (C2) GET + SET TARGET OPTIONS
    opt.target.readOnly = true;
    opt.target.dataset.max = opt.max;
    opt.target.dataset.decimal = opt.decimal;
    opt.target.addEventListener("click", numpad.show);
 
    // (C3) ATTACH CUSTOM LISTENERS
    if (opt.onselect) {
      opt.target.addEventListener("numpadok", opt.onselect);
    }
  },
 
  // (D) SHOW NUMPAD
  show: function() {
    // (D1) SET CURRENT DISPLAY VALUE
    let cv = this.value;
    if (cv == "") { cv = "0"; }
    numpad.hdisplay.value = cv;
 
    // (D2) SET MAX ALLOWED CHARACTERS
    numpad.nowMax = this.dataset.max;
 
    // (D3) SET DECIMAL
    if (this.dataset.decimal == "true") {
      numpad.hbwrap.classList.remove("noDec");
    } else {
      numpad.hbwrap.classList.add("noDec");
    }
 
    // (D4) SET CURRENT TARGET
    numpad.nowTarget = this;
 
    // (D5) SHOW NUMPAD
    numpad.hwrap.classList.add("open"); 
  },
 
  // (E) HIDE NUMPAD
  hide: function(){ numpad.hwrap.classList.remove("open"); },
};
window.addEventListener("DOMContentLoaded", numpad.init);

 

 

THE ESSENTIALS

Holy cow! That is a lot of code, and very confusing. Well, we are not going to run through the code line-by-line, but here are the essentials.

  • init() will run when the window loads. This function creates all the necessary HTML for the keypad.
  • Yes, this will only create one HTML keypad, shared among many attached input fields – We will go through the generated HTML and CSS below.
  • Next, we use attach() to set the numpad on an input field, along with the options.
  • digit() dot() delete() reset() select() are functions to handle the “keypad presses”.
  • show() is self-explanatory… This one is fired when an attached input field is clicked.
  • Finally, hide() is another Captain Obvious. Hides the numpad.

 

THE SUMMARY

The Functions
Function Description
init() Runs when the window loads. Creates the necessary HTML for the keypad.
digit() Adds selected number digit to the current value.
dot() Adds a decimal point to the current value.
delete() “Backspace”, remove a digit from the current value.
reset() Reset the current value to 0.
select() Set the current value onto the attached input field.
attach() Attach the numpad onto a selected input field.
show() Show the numpad. Fired when an attached input field is clicked.
hide() Hide the numpad.
The Properties
Property Description
hwrap HTML Reference to the keypad wrapper container.
hpad The numpad itself.
hdisplay The numeric display.
hbwrap Buttons wrapper container.
hbuttons An object containing all the keypad buttons.
nowTarget Set by show(), the currently selected input field.
nowMax Set by show(), the current maximum character limit.

 

 

KEYPAD HTML

Wondering how the complete keypad looks like? 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>

 

 

THE CSS

numpad-dark.css
/* (A) WRAPPER */
#numWrap {
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.7);
  position: fixed;
  top: 0; left: 0;
  z-index: 999;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s;
}
#numWrap.open {
  opacity: 1;
  visibility: visible;
}
 
/* (B) NUMPAD */
#numPad {
  max-width: 350px;
  background: #151515;
  margin: 50vh auto 0 auto;
  transform: translateY(-50%);
  padding: 10px;
}
 
/* (C) DISPLAY */
#numDisplay {
  box-sizing: border-box;
  width: 100%;
  border: 0;
  padding: 5px;
  margin-bottom: 10px;
  background: #000;
  color: #fff;
  font-size: 42px;
  text-align: right;
}
#numDisplay:focus { outline: none; }
#numDisplay::selection { background: none; }
 
/* (D) BUTTONS WRAPPER */
#numBWrap {
  display: grid;
  grid-template-columns: auto auto auto auto;
  grid-gap: 5px;
}
 
/* (E) BUTTONS */
#numBWrap div {
  font-size: 24px;
  color: #fff;
  text-align: center;
  padding: 15px 0;
}
#numBWrap div:hover { cursor: pointer; }
#numBWrap .num, #numBWrap .zero, #numBWrap .dot { background: #565656; }
#numBWrap .zero { grid-column: span 2; }
#numBWrap .del, #numBWrap .clr { background: #333; }
#numBWrap .cx { background: #940909; }
#numBWrap .ok { background: #115296; }
 
/* No decimal points allowed */
#numBWrap.noDec .dot { display: none; }
#numBWrap.noDec .zero { grid-column: span 3; }

No need to panic, these are literally just some cosmetics. The only few “tricky mechanisms” that you need to take note are:

  • #numWrap is “closed” by default using opacity: 0; visibility: hidden.
  • The show() function will add a .open class to #numWrap – We literally just use opacity: 0; visiblity: visible to show the keypad; The hide() function will remove the .open class.
  • A .noDec CSS class will be added to the buttons container #numBWrap if the “no decimal” option is set – We have to hide the decimal button and extend the 0 button accordingly.

 

 

USEFUL BITS

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

 

CHANGING THE LAYOUT OF THE BUTTONS

Sadly, the buttons are attached semi-manually in Javascript. 2 things to do here –

  • Change section (A5) BUTTONS in the Javascript to the layout that you want.
  • Update the CSS if you don’t want 4 buttons per row. Update sections (D) BUTTONS WRAPPER and (E) BUTTONS.

 

HOW ABOUT ADDING MORE BUTTONS?

Need more buttons for funny characters like # - *? That will be a little more challenging.

  • Create a new function to handle the button press. For example, numpad.hash = function(){ ... }.
  • Then change section (A5) BUTTONS in the Javascript to add your “custom button”. For example, buttonator("#", "hash", numpad.hash).
  • Lastly, update the CSS button layout where applicable.

 

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!

20 thoughts on “Responsive Numeric Keypad With HTML Javascript – Free Code Download”

  1. Very tidy bit of code.
    After attaching my input box to “numpad”. Is is possible to detect that the value of the input box has change on the holding document, so that a script could run which will do some update process.

    Many thanks

    1. Sadly, onchange will only trigger on user input. So the hard way:

      1) Change (C) attach, add your own “after” option to accept a function.
      2) Change (B6) select. Call the function if “after” is set.

      1. Thank you W.S. TOH, was starting to come to the same conclusion.
        Have already added an option, to display a heading on the numpad.
        Thanks for your input.

  2. Great script! But I have one question.. I want to use this in a table, so have multiple rows with the same

    The numeric keypad only pop-up when clicking the first row. No on any other.
    Is there a way to change that?

    1. 1) Remove get element by ID during attach.

      attach: function(opt){
        // (C2) GET + SET TARGET OPTIONS
        // let target = document.getElementById(opt.target);
        target = opt.target;
      }

      2) Directly pass the elements in.

      var all = document.querySelectorAll("#TABLE input[type=text]");
      for (let i of all) { numpad.attach({ target: i }); }
      
    1. Sure.

      1) Modify show() – Attach an onkey listener when the keypad is open.
      2) If the key pressed is numeric, map it to digit().
      3) If the key pressed is dot, map it to dot().
      4) If the key pressed is backspace, map it to delete().
      5) If the key pressed is enter, map it to select().
      6) If the key pressed is esc, map it to hide().
      7) Modify hide() – Detach onkey listener when the keypad is closed.

      You decide if it is worth all the trouble.

    1. There are 2 places you need to modify:
      1) In the Javascript, function init() – Change the layout of the buttons under the (A5) BUTTONS section.
      2) In the CSS, change the width of the buttons under the (D) BUTTONS WRAPPER section.

      1. I changed the layout
        // First row – 1 to 3.
        for (var i = 1; i <= 3; i++) {
        append(i, numpad.digit);
        }
        // Second row – 4 to 6.
        for (var i = 4; i <= 6; i++) {
        append(i, numpad.digit);
        }
        // Third row – 7 to 9.
        for (var i = 7; i <= 9; i++) {
        append(i, numpad.digit);
        }
        // Last row – cancel, 0 , ok
        append("✖", numpad.reset, "cx");
        append(0, numpad.digit, "zero");
        numpad.zero = button;
        append("✔", numpad.select, "ok");

        and then the width: 25% , but there aren't changes, I still have 4 buttons per row.

Leave a Comment

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