Time Editor V2

by whelkaholism

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<div data-bind="timeEditor: { boundField: Time, includeSeconds: true }"></div>
<div data-bind="timeEditor: { boundField: Time2, includeSeconds: false }"></div>

Secs: <div data-bind="text: Time() == null ? 'NULL' : Time()"></div>
<hr>
!Secs: <div data-bind="text: Time2() == null ? 'NULL' : Time2()"></div>
<hr>
<button data-bind="click: set">
Set
</button>

JavaScript

ko.bindingHandlers.timeEditor = {
    init: function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
    {        
        var o = ko.unwrap(f_valueaccessor())
        var hasoptions = !!o.boundField;
        
        var field = hasoptions ? o.boundField : f_valueaccessor();
        var options = hasoptions ? o : {};
        var hassecs = options.includeSeconds !== false;

        var markup =
            '<input class="ui-hh" placeholder="HH" type="text" data-bind="value: HH" maxlength="2" /><span class="ui-sep-hhmm">:</span>' +
            '<input class="ui-mm" placeholder="MM" type="text" data-bind="value: MM" maxlength="2" />';
            
            if(hassecs)
            {
            markup += '<span class="ui-sep-mmss">:</span>';
            markup += '<input class="ui-ss" placeholder="SS" type="text" data-bind="value: SS" maxlength="2" />';
            }

        $(markup).appendTo(el);
        $(el).addClass('ui-time-editor');

        var hhobs = ko.observable();
        var mmobs = ko.observable();
        var ssobs = ko.observable();

        var max = {
            h: 23,
            m: 59,
            s: 59
        };

        var __set = function(part, partval)
        {
        		var curr = {
            	h: hhobs(),
              m: mmobs(),
              s: ssobs()
            };
            
            var x = parseInt(partval, 10);
            x = (x >= 0 && x < 10 ? '0' + x : x) + '';
            
            console.log('__set', x, part, max[part], curr);

            if (options.isDuration !== true && x > max[part])
                x = max[part];
            else if (x < 0)
                x = 0;
                
						curr[part] = x;
						this(x);
						
            var hok = !isNaN(parseInt(curr.h, 10));
            var mok= !isNaN(parseInt(curr.m, 10));
            var sok = !isNaN(parseInt(curr.s, 10));
                        
            if(hok && mok && (!hassecs || sok))
            	field(curr.h + ':' + curr.m +...