JSFiddle - React, Tailwind, and code Playground

by jdanyow

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<form role="form">
    <div class="form-group">
        <label>Integer</label>
        <input id="int" class="form-control" type="number" min="0" max="9999999" data-bind="number: intProp, blankSubstitute: null" />
        <p class="help-block">Current value:&nbsp;<span data-bind="text: intProp"></span>

        </p>
    </div>
    <div class="form-group">
        <label>Decimal</label>
        <input id="dec" class="form-control" type="number" min="0" max="9999999.99" data-bind="number: decProp, blankSubstitute: 0" />
        <p class="help-block">Current value:&nbsp;<span data-bind="text: decProp"></span>

        </p>
    </div>
    <div class="form-group currency">
        <label>Currency</label> <span class="currency-sign">$</span>

        <input id="cur" class="form-control" type="number" min="0" max="9999999.99" data-bind="number: curProp, blankSubstitute: null" />
        <p class="help-block">Current value:&nbsp;<span data-bind="text: curProp"></span>

        </p>
    </div>
</form>

CSS

.form-group.currency > span.currency-sign {
    display: block;
    margin-bottom: -27px;
    margin-left: 12.5px;
}

.currency > input.form-control {
    padding-left: 22px;
}

JavaScript

$(document).ready(function () {

    function handleKeyDown(e) {
        // don't allow period if this is an integer field.
        var periodKeyCode = this.id === 'int' ? -99999 : 190;

        // Allow: backspace, delete, tab, escape, enter and .
        if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, periodKeyCode]) !== -1 ||
        // Allow: Ctrl+A
        (e.keyCode == 65 && e.ctrlKey === true) ||
        // Allow: home, end, left, right
        (e.keyCode >= 35 && e.keyCode <= 39)) {
            // let it happen, don't do anything
            return;
        }

        // Ensure that it is a number and stop the keypress
        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
            e.preventDefault();
        }
    };

    function isInputValid(input) {
        var regex = /^\d{0,7}(\.\d{0,2}){0,1}$/;
        return regex.test(input.value);
    }

    function displayValidState($formGroup, isValid) {
        if (isValid) {
            $formGroup.removeClass('has-error');
        } else {
            $formGroup.addClass('has-error');
        }
    }

    ko.bindingHandlers.number = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var $element = $(element),
                $formGroup = $element.closest('.form-group'),
                observable = valueAccessor(),
                previousValue = observable(),
                allBindings = allBindingsAccessor(),
                blankSubstitute = 0,
                changeTimeout = 0;

            // initialize the input.
            $element.val(previousValue);

            // custom substitute value for blank?
            if (allBindings.hasOwnProperty('blankSubstitute')) blankSubstitute = allBindings.blankSubstitute;

            $element.on('keydown', handleKeyDown);
            $element.on('change keyup keypress paste', function (e) {
                clearTimeout(changeTimeout);
            ...