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: <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: <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: <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);
...