Welcome to a tutorial on how to create a time picker using pure Javascript and CSS. Yes, there are plenty of time picker plugins available on the Internet. But some of them require a third-party library, and it simply does not make sense to load an entire library for a single-time picker. So here it is, a sharing of my simple time picker – Read on!
TABLE OF CONTENTS
JAVASCRIPT TIMEPICKER
All right, let us now move into a demo and details on how the time picker works.
DEMO & HOW TO USE
BASIC TIME PICKER
<!-- (A) LOAD THE CSS + JS -->
<link href="time-pick.css" rel="stylesheet">
<script src="time-pick.js"></script>
<!-- (B) POPUP TIME PICKER -->
<input type="text" id="demoA">
<!-- (C) ATTACH -->
<script>
tp.attach({
target: document.getElementById("demoA")
});
</script>
- Include the time picker Javascript and CSS files. Captain Obvious at your service.
- Define a
<input type="text">
as usual. - Finally, use
tp.attach({ target : HTML FIELD })
to attach the time picker.
TIME PICKER OPTIONS
tp.attach({
target: document.getElementById("demoB"),
"24": true, // 24 hours
after : time => alert(time) // run function after select
});
That’s all. This simple time picker only has 2 optional options:
24
Use 24 hour time format, defaults tofalse
.after
Function to call after selecting the time.
PART 1) TIME PICKER INITIALIZE
// (A) INIT - GENERATE TIME PICKER HTML
hwrap : null, // entire html time picker
hhr : null, // html hour value
hmin : null, // html min value
hap : null, // html am/pm value
init : () => {
// (A1) ADD TIME PICKER TO BODY
tp.hwrap = document.createElement("div");
tp.hwrap.id = "tp-wrap";
document.body.appendChild(tp.hwrap);
// (A2) TIME PICKER INNER HTML
tp.hwrap.innerHTML =
`<div id="tp-box">
<div class="tp-cell" id="tp-hr">
<div class="tp-up">︿</div> <div class="tp-val">0</div> <div class="tp-down">﹀</div>
</div>
<div class="tp-cell" id="tp-min">
<div class="tp-up">︿</div> <div class="tp-val">0</div> <div class="tp-down">﹀</div>
</div>
<div class="tp-cell" id="tp-ap">
<div class="tp-up">︿</div> <div class="tp-val">AM</div> <div class="tp-down">﹀</div>
</div>
<button id="tp-close" onclick="tp.hwrap.classList.remove('show')">Close</button>
<button id="tp-set" onclick="tp.set()">Set</button>
</div>`;
// (A3) GET VALUE ELEMENTS + SET CLICK ACTIONS
for (let segment of ["hr", "min", "ap"]) {
let up = tp.hwrap.querySelector(`#tp-${segment} .tp-up`),
down = tp.hwrap.querySelector(`#tp-${segment} .tp-down`);
tp["h"+segment] = tp.hwrap.querySelector(`#tp-${segment} .tp-val`);
if (segment=="ap") {
up.onclick = () => tp.spin(true, segment);
down.onclick = () => tp.spin(true, segment);
} else {
up.onmousedown = () => tp.spin(true, segment);
down.onmousedown = () => tp.spin(false, segment);
up.onmouseup = () => tp.spin(null);
down.onmouseup = () => tp.spin(null);
up.onmouseleave = () => tp.spin(null);
down.onmouseleave = () => tp.spin(null);
}
}
},
document.addEventListener("DOMContentLoaded", tp.init);
The first thing that runs on page load is tp.init()
. It may look intimidating, but keep calm and look carefully. All it does is generate the time picker HTML <div id="tp-wrap">
to the page – All the inner HTML is right there are A2.
PART 2) TIME PICKER HOUR/MIN/AM/PM SPINNER
// (B) SPIN HOUR/MIN/AM/PM
// direction : true (up), false (down), null (stop)
// segment : "hr", "min", "ap" (am/pm)
timer : null, // for "continous" time spin
minhr : 1, // min spin limit for hour
maxhr : 12, // max spin limit for hour
minmin : 0, // min spin limit for minute
maxmin : 59, // max spin limit for minute
spin : (direction, segment) => {
// (B1) CLEAR TIMER
if (direction==null) { if (tp.timer!=null) {
clearTimeout(tp.timer);
tp.timer = null;
}}
// (B2) SPIN FOR AM/PM
else if (segment=="ap") { tp.hap.innerHTML = tp.hap.innerHTML=="AM" ? "PM" : "AM"; }
// (B3) SPIN FOR HR/MIN
else {
// (B3-1) INCREMENT/DECREMENT
let next = +tp["h"+segment].innerHTML;
next = direction ? next+1 : next-1;
// (B3-2) MIN/MAX
if (segment=="hr") {
if (next > tp.maxhr) { next = tp.maxhr; }
if (next < tp.minhr) { next = tp.minhr; }
} else {
if (next > tp.maxmin) { next = tp.maxmin; }
if (next < tp.minmin) { next = tp.minmin; }
}
// (B3-3) SET VALUE
if (next<10) { next = "0"+next; }
tp["h"+segment].innerHTML = next;
// (B3-4) KEEP ROLLING - LOWER TIMEOUT WILL SPIN FASTER
tp.timer = setTimeout(() => tp.spin(direction, segment), 100);
}
},
Next, I figured that it will be stupid to click on the hour/minute hundreds of times to set it. So this function is the essential driver behind “hold mouse down to spin”.
PART 3) ATTACH TIME PICKER
// (C) ATTACH TIME PICKER TO HTML FIELD
// target : html field to attach to
// 24 : 24 hours time? default false.
// after : optional, function to run after selecting time
attach : instance => {
// (C1) READONLY FIELD + NO AUTOCOMPLETE
// IMPORTANT, PREVENTS ON-SCREEN KEYBOARD
instance.target.readOnly = true;
instance.target.setAttribute("autocomplete", "off");
// (C2) DEFAULT 12 HOURS MODE
if (instance["24"]==undefined) { instance["24"] = false; }
// (C3) CLICK TO OPEN TIME PICKER
instance.target.addEventListener("click", () => tp.show(instance));
},
You already know this one, we call tp.attach()
to attach the time picker to an <input>
field. Basically, we attach an onclick
to display the time picker.
PART 4) DISPLAY THE TIME PICKER
// (D) SHOW TIME PICKER
setfield : null, // set selected time to this html field
set24 : false, // 24 hours mode? default false.
setafter : null, // run this after selecting time
show : (instance) => {
// (D1) INIT FIELDS TO SET + OPTIONS
tp.setfield = instance.target;
tp.setafter = instance.after;
tp.set24 = instance["24"];
tp.minhr = tp.set24 ? 0 : 1 ;
tp.maxhr = tp.set24 ? 23 : 12 ;
// (D2) READ CURRENT VALUE
let val = tp.setfield.value;
if (val=="") {
tp.hhr.innerHTML = "0"+tp.minhr;
tp.hmin.innerHTML = "0"+tp.minmin;
tp.hap.innerHTML = "AM";
} else {
tp.hhr.innerHTML = val.substring(0, 2);
if (tp.set24) {
tp.hmin.innerHTML = val.substring(2, 4);
} else {
tp.hmin.innerHTML = val.substring(3, 5);
tp.hap.innerHTML = val.substring(6, 8);
}
}
// (D3) SHOW TIME PICKER
if (tp.set24) { tp.hwrap.classList.add("tp-24"); }
else { tp.hwrap.classList.remove("tp-24"); }
tp.hwrap.classList.add("show");
},
tp.show()
is called when the user clicks on an attached <input>
field. Not going to explain line-by-line, but it sets some internal flags, then adapts the selected time from the field to the time picker.
PART 5) SET SELECTED TIME
// (E) SET TIME
set : () => {
// (E1) TIME TO FIELD
if (tp.set24) {
tp.setfield.value = tp.hhr.innerHTML + tp.hmin.innerHTML;
} else {
tp.setfield.value = tp.hhr.innerHTML + ":" + tp.hmin.innerHTML + " " + tp.hap.innerHTML;
}
tp.hwrap.classList.remove("show");
// (E2) RUN AFTER, IF SET
if (tp.setafter) { tp.setafter(tp.setfield.value); }
}
Lastly, this should be very obvious – Set the selected time onto the HTML field.
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 project, and here is a small section on some extras that may be useful to you.
CHANGING THE TIME FORMAT
- Modify
set()
, sectionE1
. - Also, remember to change how it adapts existing values in
show()
, sectionD2
.
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- Literal Template – CanIUse
This time picker will work on all Grade A modern browsers.
LINKS & REFERENCES
- Pure Javascript Date Picker – Code Boxx
- Example on CodePen – Javascript Timepicker
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you to create a better website, and if you have anything to share with this guide, please feel free to comment below. Good luck and happy coding!