JSFiddle - React, Tailwind, and code Playground
by MKGaru
HTML
<script src="https://rawgit.com/SteveSanderson/knockout-es5/master/dist/knockout-es5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sugar/1.4.1/sugar-full.min.js"></script>
<ol>
<li><input type="time" data-bind="value:time1">
<li><input type="time" data-bind="value:time2" step="600">
<li><time-picker params="time2"/>
<li><time-picker params="time3,'17:30'"/>
</ol>
CSS
html,
body{
height: 100%;
}
time-picker{
display:inline-block;
background:white;
border:solid 1px #ccc;
padding:0.1em;
padding-right:1.2em;
position:relative;
}
time-picker input{
border:none;
outline:none;
background:transparent;
width:1.5em;
user-select:none;
-webkit-user-select:none;
}
time-picker input::selection {
background:transparent;
}
/*time-picker input:focus,*/
time-picker input.focus{
background:#ACCEF7;
}
time-picker .spin-buttons{
display:inline-flex;
flex-direction:column;
visibility: hidden;
transform: scale(0.5);
transform-origin: top left;
position: absolute;
top: 0.1em;
right: -0.5em;
}
.time-picker.focus .spin-buttons,
time-picker:hover .spin-buttons,
time-picker:focus .spin-buttons{
visibility: visible;
}
time-picker .spin-buttons button{
border:none;
outline:none;
}
time-picker .spin-buttons button:hover{
background:lightgray;
}
time-picker .spin-buttons button:active{
background:gray;
}
TypeScript
class VM{
public time1 = '';
public time2 = '';
public time3 = '';
constructor(){
ko.track(this);
}
}
class TimePicker{
public default='08:30';
public hour='- -';
public minute='- -';
public hourInput = null;
public minuteInput = null;
public target = null;
constructor(params,info){
var picker = this;
ko.track(picker);
var keys = Object.keys(params);
var name = keys[0];
var prop = ko.getObservable(ko.contextFor(info.element),name);
if(keys.length>=2){
if(Number.isInteger(+keys[1][0])){
picker.default = keys[1];
}
else{
picker.default = ko.getObservable(ko.contextFor(info.element),keys[1]);
}
}
if(!prop) prop = ko.getObservable(ko.dataFor(info.element),name);
prop.subscribe(()=>{
var value = prop.peek();
if(!value) return;
var date = Date.create(value);
if(date.isValid()){
picker.hour = date.getHours().pad(2);
picker.minute = date.getMinutes().pad(2);
ko.getObservable(picker,'hour').valueHasMutated();
ko.getObservable(picker,'minute').valueHasMutated();
}
});
prop.valueHasMutated();
function updateInput(){
if(picker.hour === '' || picker.hour=='- -' || picker.minute===''||picker.minute=='- -'){
prop(picker.default);
return;
}
let h = Number(picker.hour);
if(isNaN(h)) picker.hour = '- -';
else picker.hour = h.pad(2);
if(h>23) picker.hour = Math.floor(h/24).pad(2);
let m = Number(picker.minute);
if(isNaN(m)) picker.minute = '- -';
else picker.minute = m.pad(2);
if(m>59) picker.minute = Math.floor(m/60).pad(2);
let value = [picker.hour,picker.minute].join(':');
if(value != prop.peek())
prop(value);
}
ko.getObservable(picker,'hour').subscribe(()=>{
return updateInput();
});
ko.getObservable(picker,'minute').subscribe(()=>{
return updateInput();
});
setTimeout(()=>{
//info.element.addEventListener('keydown',(e)=>{
...