Create clock picker input with JavaScript and CSS.

by whelkaholism

HTML

<input type="time" data-bind="clockpicker: Time, clockpickerOptions: { inline: false, closeAfterMinuteEntry: true }" />
<div>
  <h2 data-bind="text: Time"></h2>
</div>

CSS

.clock-picker {
  box-sizing: border-box;
  position: relative;
  background: #202020;
  display: inline-block;
}

.clock-picker .current-time {
  box-sizing: border-box;
  color: #ffffff;
  font-weight: 900;
  font-size: 2em;
  text-align: center;
  padding: 0.5em;
}

.clock-picker .current-time b {
  cursor: pointer;
}

.clock-picker .clock {
  box-sizing: border-box;
  position: relative;
  width: 300px;
  height: 300px;
  background: #404040;
}

.clock-picker .face {
  box-sizing: border-box;
  position: absolute;
  background: #606060;
  border-radius: 50%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  outline: none;
}

.clock-picker .t {
  box-sizing: border-box;
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #101010;
  color: #ffffff;
  border-radius: 50%;
  cursor: pointer;
}

.clock-picker .t:hover {
  background:#303030;
}

.clock-picker .t.selected {
  background:#ffffff;
  color: #000000;
}

.clock-picker.popup {
  position: absolute;
  left: 0;
}
.clock-picker.popup.hide {
  opacity: 0;
}

JavaScript

(function()
{
    window.ClockPicker = function(el, options)
    {
        const _this = this;
        var _inline = options && options.inline;

        var _nodes = {
            h: [],
            m: []
        };

        this.padding = {
            h: 10
        };

        this.sizes = {
            outerTimes: 7,
            innerTimes: 9,
            innerRadius: 2.8
        };

        this.h = '';
        this.m = '';
        this.mStep = 5;

        // ==================================================================================================================================
        // Set the current time from a string, making sure to round to supported values
        this.setTime = function(t, updateinput, triggerevents)
        {
            var m;

            if (m = /(\d\d):(\d\d)/.exec(t))
            {
                var v = {
                    h: parseInt(m[1]),
                    m: Math.round(parseInt(m[2]) / _this.mStep) * _this.mStep
                };

                _this.setValue(v.h, 'h', false, false, triggerevents);
                _this.setValue(v.m, 'm', false, false, triggerevents);

                ['h', 'm'].forEach(function(x)
                {
                    _nodes[x].forEach(function(y)
                    {
                        y.classList.remove('selected');
                        (y.__value == v[x]) && y.classList.add('selected');
                    });
                });

                if (updateinput !== false)
                    _this.input.value = _this.getTime();
            }
        };

        // Get the current time as a full string representation
        this.getTime = function()
        {
            return (_this.h || '00') + ':' + (_this.m || '00');
        };

        // ==================================================================================================================================
        // Render...