Following on from another question I asked, i really didnt seem to be getting anywhere. Due to my ineptitude. I chose the guys answer because , well he answered my question.
You could, in the change
event of the input, check if the number format is OK. This code will try to get the number and remove anything else: (I'm assuming you use jQuery, if not, please do)
$('#price').change(function() {
$(this).val($(this).val().match(/\d*\.?\d+/));
});
See it working here.
EDIT: if you don't have jQuery, this code does the same (at least in Chrome):
document.getElementById('price').onchange = function() {
this.value = this.value.match(/\d*\.?\d+/);
};
EDIT 2: not sure if I follow, but you could add this too to prevent letters and other characters before the change
event:
$('#price').keypress(function(event) {
var code = (event.keyCode ? event.keyCode : event.which);
if (!(
(code >= 48 && code <= 57) //numbers
|| (code == 46) //period
)
|| (code == 46 && $(this).val().indexOf('.') != -1)
)
event.preventDefault();
});
Cambraca aproach kind of works, but the best one is the last mentioned approach , you cancel the keypress event filtering the keys before it shows up instead of undoing what was already done. A consequence of changing the value after the fact is that it may affect the position of the caret in the field.
Here's an example of abstracting the idea in a cross-browser way. Somebody should port this to a jQuery plugin http://www.qodo.co.uk/assets/files/javascript-restrict-keyboard-character-input.html
Ok, I guess I'll port it. But I'm not a jQuery guy so this is an untested bare bones jQuery plugin that uses their code
http://jsfiddle.net/mendesjuan/VNSU7/3
(function( $ ) {
$.fn.restrict = function(regExp, additionalRestriction) {
function restrictCharacters(myfield, e, restrictionType) {
var code = e.which;
var character = String.fromCharCode(code);
// if they pressed esc... remove focus from field...
if (code==27) { this.blur(); return false; }
// ignore if they are press other keys
// strange because code: 39 is the down key AND ' key...
// and DEL also equals .
if (!e.originalEvent.ctrlKey && code!=9 && code!=8 && code!=36 && code!=37 && code!=38 && (code!=39 || (code==39 && character=="'")) && code!=40) {
if (character.match(restrictionType)) {
return additionalRestriction(myfield.value, character);
} else {
return false;
}
}
}
this.keypress(function(e){
if (!restrictCharacters(this, e, regExp)) {
e.preventDefault();
}
});
};
})( jQuery );
$('#field').restrict(/[0-9\.]/g, function (currentValue, newChar) {
return !(currentValue.indexOf('.') != -1 && newChar == ".");
});
Here is my solution(It also validates data/values copy&pasted):
function InputValidator(input, validationType, validChars) {
if (input === null || input.nodeType !== 1 || input.type !== 'text' && input.type !== 'number')
throw ('Please specify a valid input');
if (!(InputValidator.ValidationType.hasOwnProperty(validationType) || validationType))
throw 'Please specify a valid Validation type';
input.InputValidator = this;
input.InputValidator.ValidCodes = [];
input.InputValidator.ValidCodes.Add = function (item) {
this[this.length] = item;
};
input.InputValidator.ValidCodes.hasValue = function (value, target) {
var i;
for (i = 0; i < this.length; i++) {
if (typeof (target) === 'undefined') {
if (this[i] === value)
return true;
}
else {
if (this[i][target] === value)
return true;
}
}
return false;
};
var commandKeys = {
'backspace': 8,
'tab': 9,
'enter': 13,
'shift': 16,
'ctrl': 17,
'alt': 18,
'pause/break': 19,
'caps lock': 20,
'escape': 27,
'page up': 33,
'page down': 34,
'end': 35,
'home': 36,
'left arrow': 37,
'up arrow': 38,
'right arrow': 39,
'down arrow': 40,
'insert': 45,
'delete': 46,
'left window key': 91,
'right window key': 92,
'select key': 93,
/*creates Confusion in IE */
//'f1': 112,
//'f2': 113,
//'f3': 114,
//'f4': 115,
//'f5': 116,
//'f6': 117,
//'f7': 118,
//'f8': 119,
//'f9': 120,
//'f10': 121,
//'f11': 122,
//'f12': 123,
'num lock': 144,
'scroll lock': 145,
};
commandKeys.hasValue = function (value) {
for (var a in this) {
if (this[a] === value)
return true;
}
return false;
};
function getCharCodes(arrTarget, chars) {
for (var i = 0; i < chars.length; i++) {
arrTarget.Add(chars[i].charCodeAt(0));
}
}
function triggerEvent(name, element) {
if (document.createEventObject) {
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on' + name, evt)
}
else {
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(name, true, true); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
if (validationType == InputValidator.ValidationType.Custom) {
if (typeof (validChars) === 'undefined')
throw 'Please add valid characters';
getCharCodes(input.InputValidator.ValidCodes, validChars);
}
else if (validationType == InputValidator.ValidationType.Decimal) {
getCharCodes(input.InputValidator.ValidCodes, '0123456789.');
}
else if (validationType == InputValidator.ValidationType.Numeric) {
getCharCodes(input.InputValidator.ValidCodes, '0123456789');
}
input.InputValidator.ValidateChar = function (c) {
return this.ValidCodes.hasValue(c.charCodeAt(0));
}
input.InputValidator.ValidateString = function (s) {
var arr = s.split('');
for (var i = 0; i < arr.length; i++) {
if (!this.ValidateChar(arr[i])) {
arr[i] = '';
}
}
return arr.join('');
}
function bindEvent(el, eventName, eventHandler) {
if (el.addEventListener) {
el.addEventListener(eventName, eventHandler, false);
} else if (el.attachEvent) {
el.attachEvent('on' + eventName, eventHandler);
}
}
function getCaretPosition(i) {
if (!i) return;
if ('selectionStart' in i) {
return i.selectionStart;
}
else {
if (document.selection) {
var sel = document.selection.createRange();
var selLen = document.selection.createRange().text.length;
sel.moveStart('character', -i.value.length);
return sel.text.length - selLen;
}
}
}
function setCursor(node, pos) {
var node = (typeof (node) === "string" || node instanceof String) ? document.getElementById(node) : node;
if (!node) {
return false;
}
else if (node.createTextRange) {
var textRange = node.createTextRange();
textRange.collapse(true);
textRange.moveEnd(pos);
textRange.moveStart(pos);
textRange.select();
return true;
} else if (node.setSelectionRange) {
node.setSelectionRange(pos, pos);
return true;
}
return false;
}
function validateActive() {
if (input.isActive) {
var pos = getCaretPosition(input);
var arr = input.value.split('');
for (var i = 0; i < arr.length; i++) {
if (!this.ValidateChar(arr[i])) {
arr[i] = '';
if (pos > i)
pos--;
}
}
console.log('before : ' + input.value);
input.value = arr.join('');
console.log('after : ' + input.value, input);
setCursor(input, pos);
setTimeout(validateActive, 10);
}
}
bindEvent(input, 'keypress', function (e) {
var evt = e || window.event;
var charCode = evt.which || evt.keyCode;
if (!input.InputValidator.ValidCodes.hasValue(charCode) && !commandKeys.hasValue(charCode)) {
if (evt.preventDefault) {
evt.preventDefault();
evt.stopPropagation();
}
return false;
}
});
bindEvent(input, 'keyup', function (e) {
var evt = e || window.event;
var charCode = evt.which || evt.keyCode;
if (!input.InputValidator.ValidCodes.hasValue(charCode) && !commandKeys.hasValue(charCode)) {
if (evt.preventDefault) {
evt.preventDefault();
evt.stopPropagation();
}
return false;
}
});
bindEvent(input, 'change', function (e) {
var dt = input.value;
input.value = input.InputValidator.ValidateString(input.value);
if (input.value !== dt)
triggerEvent('change', input);
});
bindEvent(input, 'blur', function (e) {
var dt = input.value;
input.value = input.InputValidator.ValidateString(input.value);
input.isActive = false;
if (input.value !== dt)
triggerEvent('blur', input);
});
bindEvent(input, 'paste', function (e) {
var evt = e || window.event;
var svt = input.value;
if (evt && evt.clipboardData && evt.clipboardData.getData) {// Webkit - get data from clipboard, put into editdiv, cleanup, then cancel event
if (/text\/html/.test(evt.clipboardData.types)) {
var dt = evt.clipboardData.getData('text/html');
input.value = input.InputValidator.ValidateString(dt);
if (input.value !== dt)
triggerEvent('change', input);
}
else if (/text\/plain/.test(e.clipboardData.types)) {
var dt = evt.clipboardData.getData('text/plain');
input.value = input.InputValidator.ValidateString(dt);
if (input.value !== dt)
triggerEvent('change', input);
}
else {
input.value = '';
}
waitforpastedata(input, svt);
if (e.preventDefault) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
else {// Everything else - empty editdiv and allow browser to paste content into it, then cleanup
input.value = '';
waitforpastedata(input, svt);
return true;
}
});
bindEvent(input, 'select', function (e) {
var evt = e || window.event;
if (evt.preventDefault) {
evt.preventDefault();
evt.stopPropagation();
}
return false;
});
bindEvent(input, 'selectstart', function (e) {
var evt = e || window.event;
if (evt.preventDefault) {
evt.preventDefault();
evt.stopPropagation();
}
return false;
});
/* no need to validate wile active,
removing F keys fixed IE compatability*/
//bindEvent(input, 'fucus', function (e) {
// input.isActive = true;
// validateActive();
//});
//validate current value of the textbox
{
var dt = input.value;
input.value = input.InputValidator.ValidateString(input.value);
//trigger event to indicate value has changed
if (input.value !== dt)
triggerEvent('change', input);
}
function waitforpastedata(elem, savedcontent) {
if (elem.value !== '') {
var dt = input.value;
elem.value = elem.InputValidator.ValidateString(elem.value);
if (input.value !== dt)
triggerEvent('change', input);
}
else {
var that = {
e: elem,
s: savedcontent
}
that.callself = function () {
waitforpastedata(that.e, that.s)
}
setTimeout(that.callself, 10);
}
}
}
InputValidator.ValidationType = new (function (types) {
for (var i = 0; i < types.length; i++) {
this[types[i]] = types[i];
}
})(['Numeric', 'Custom', 'Decimal']);
To apply it to an input, do the following :
new InputValidator(document.getElementById('txtValidate'), InputValidator.ValidationType.Decimal);/* Numeric or Custom */
If you specify Custom as the validation type you have to specify the valid characters. eg :
new InputValidator(document.getElementById('txtValidate'), InputValidator.ValidationType.Custom,'1234abc');