I need to validate a form textfield that's bound to a property of a model using EmberJS.
I want the user to only be able to type valid, positive numbers.
I know of jQuery.isNumber(), but I don't know how to wire it to the field.
I tried writing explicit getter/setter functions on the model's property using Ember.computed(...), but it didn't work.
Is there something similar to WinForms onChanging() event that I can hook up to?
There are a number of ways to do this sort of thing. Here we can accomplish this using bindings and observers.
First lets create a function that will always return a number.
var onlyNumber = function(input) {
return input.toString().replace(/[^\d.]/g, "");
};
Using that we can do the following
App = Ember.Application.create();
App.person = Ember.Object.create({
age: 42
});
App.NumberField = Ember.TextField.extend({
valueBinding: Ember.Binding.from("App.person.age").transform(onlyNumber),
_cleanValue: function() {
this.set('value', onlyNumber(this.get('value')));
}.observes('value')
});
1) We are creating a Binding to the Person's age, but anything that passes through this binding can only be a number. See Ember.Binding to/from transforms for more details.
2) We are observing the text field's value and setting it to be only a number when it changes. If the user enters '42a' we will immediately set it back to '42'. Note that even though '42a' was in the text input for a brief second it would not have been able to pass through the binding because of our transform.
Here is a fiddle showing this example: http://jsfiddle.net/nDBgC/
You could add a keyDown event handler on your TextField, see http://jsfiddle.net/pangratz666/SKJfF/:
App.NumberTextField = Ember.TextField.extend({
// implementation of this function, see http://stackoverflow.com/a/995193/65542
keyDown: function(event) {
// Allow: backspace, delete, tab, escape, and enter
if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
// Allow: Ctrl+A
(event.keyCode == 65 && event.ctrlKey === true) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
event.preventDefault();
}
}
}
});
Code (handles only numeric input and allows binding of number rather than string, if desired):
App.NumberFieldComponent = Ember.TextField.extend({
tagName: "input",
type: "number",
numericValue: function(key, value) {
if (arguments.length === 1) {
return parseFloat(this.get("value"));
} else {
return this.set("value", (value !== void 0 ? "" + value : ""));
}
}.property("value"),
didInsertElement: function() {
return this.$().keypress(function(key) {
if ((key.charCode !== 46) && (key.charCode !== 45) && (key.charCode < 48 || key.charCode > 57)) {
return false;
}
});
}
});
Template:
{{number-field numericValue=someNumericProperty}}
This is an updated answer (from #neverfox) for the latest Ember version (Ember-cli 2.0). It is written in coffeescript, and a bit altered to match the becomeFocus example (http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/focusing_a_textfield_after_its_been_inserted/)
Generate the component:
ember g component number-field
Change the blueprint code (app/components/number-field.coffee) to
`import Ember from 'ember'`
NumberFieldComponent = Ember.Component.extend
tagName: "input"
type: "number"
numericValue: ( (key, value) ->
if arguments.length == 1
parseFloat(this.get('value'))
else
return this.set("value", (value? ? "" + value : ""))
).property('value')
assignFilter: ( ->
this.$().keypress (key) ->
if ((key.charCode != 46) && (key.charCode != 45) && (key.charCode < 48 || key.charCode > 57))
false
).on('didInsertElement')
`export default NumberFieldComponent`
Related
If all of the text in a form field is selected and then the Backspace or Delete key are used, I want to be able to run some additional code. I have tried using change, blur, keypress, keydown. None seem to work.
Example that doesn't work:
$('input[id^=txtDate_]').on('keydown', function() {
enableSaveChanges();
});
Here is one way - http://jsfiddle.net/jayblanchard/6Uq85/
$('textarea[name="foo"]').keyup(function(e) {
var currentText = $(this).val();
if( 0 == currentText.length && (e.keyCode = 46 || e.keyCode == 8)) {
console.log('empty');
}
});
I should add that I am a fan of keyup() here as the event order for keypress,keydown and keyup are different. You can test to see which makes more sense for you. The reason that I use keyup here is because the textarea (or input) isn't actually empty when you press the key.
Use the key codes for 'delete' and 'backspace'
delete = 46
backspace = 8
example:
HTML:
<input type="text" id="input">
jQuery:
jQuery('#input').keyup(function(e) {
var str = jQuery('#input').val();
if( (e.keyCode == 46 || e.keyCode == 8) && str == "" ) {
alert("Hey");
}
});
EDITED: check for empty input field
Try this way for
<input type="txt" id="txt"/>
$('#test').keyup(function(e){
if($('#test').val() == '' && e.keyCode == 46 || e.keyCode == 8)){
console.log('Input is emptied');
}
});
I am doing validation on an input type='text' element. I have wired up the 'paste' and the 'keydown' events to trap the input and restrict it to just numbers. The keydown seems to work without a hitch, however, I could not seem to get any of the browsers to actually NOT PASTE the text into the field (I see that there is a beforepaste event, which may be the ticket -- however it appears to not be supported by firefox. In the end, I resulted to just blanking out the input if the value was not a number. This causes a momentary flicker, but seems to work.
Is there a cleaner way to do this? Am I missing something? Is there anyway to prevent the flicker? I know the HTML5 has a type='number', but I'm not ready to go there yet.
<input type="text" id="number" />
<script type="text/javascript">
$(document).ready(function () {
enableNumericOnlyEntry("#number");
function enableNumericOnlyEntry(object) {
$(object).bind('paste', numericOnlyPaste);
$(object).bind('keydown', null, numericOnlyKeyDown);
function numericOnlyPaste(event) {
var inputText = "";
var element = event.target;
setTimeout(function () {
var text = $(element).val();
if (isNaN(text)) {
$(element).val("")
return false;
}
}, 0);
}
function numericOnlyKeyDown(event) {
// Allow: backspace, delete, tab, escape, and enter
if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
// Allow: Ctrl+A/a
(event.keyCode == 65 || event.keyCode == 97) && (event.ctrlKey === true) ||
// Allow: Ctrl+C/c
(event.keyCode == 67 || event.keyCode == 99) && (event.ctrlKey === true) ||
// Allow: Ctrl+V/v
(event.keyCode == 86 || event.keyCode == 118) && (event.ctrlKey === true) ||
// Allow: Ctrl+X/x
(event.keyCode == 88 || event.keyCode == 120) && (event.ctrlKey === true) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return true;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
return false;
}
}
}
}
});
I've used this project to create a field that is a masked edit box, you could remove the underscore to it also so it doesn't look like a masked edit. Really easy to use: http://digitalbush.com/projects/masked-input-plugin/
then you'd use something like $("#box").mask("9999999"); and your good to go, works great!
HTML5's <input type="number"> is really where you want to go with this. If you're working with browsers that support it (basically everything except Safari and old versions of IE), it does everything you want.
That said, why not register an onpaste handler so you can reduce pasted content to just numbers after the user pastes?
I'm working on a textfield working with the kind of validation that wouldn't let you enter other than numeric values. As so, my initial code looked quite simple and similar to this:
$(textField).onKeyPress(function(e) {
if (e.which < 48 && e.which > 57)
e.preventDefault();
});
This is fairly strightforward, but turns that (in the latest version of all browsers) Firefox will make this also prevent movement with the arrow keys and delete/backspace keys, whereas the other browsers would not.
Looking around I found that I would need to also check for these keys, and check for different properties exposed in the e event reference.
My final code looks something like this:
$(textField).onKeyPress(function(e) {
var code = e.which || e.keyCode;
if (code > 31 // is not a control key
&& (code < 37 || code > 40) // is not an arrow key
&& (code < 48 || code > 57) // is not numeric
&& (code != 46) // is not the delete key
)
e.preventDefault();
});
However, this feels to be too much to solve a fairly simple problem as just preventing non-numeric.
What am I doing wrong? Which is the best practice in terms of this kind of validation?
We'll respond to both keypresses, and the blur event. When somebody press a key, we check to see if the key entered is a number. If it is, we permit it. Otherwise, we prevent it.
If the field is blurred, we remove any non-numerical values, and all those values that follow. This will prevent the user from pasting in non-numerical strings:
$("#textfield").on("keypress blur", function(e){
if ( e.type === "keypress" )
return !!String.fromCharCode(e.which).match(/^\d$/);
this.value = this.value.replace(/[^\d].+/, "");
});
Demo: http://jsfiddle.net/jonathansampson/S7VhV/5/
Working demo http://jsfiddle.net/Pb2eR/23/ Updated Copy/Paste demo: http://jsfiddle.net/Pb2eR/47/ (In this demo wit you copy paste string with characters it won't allow else it will allow number to be copy pasted: tested in safari)
Demo for arrow key to work http://jsfiddle.net/gpAUf/
This will help you.
Note: in this version even if you copy paste it will set it to empty input box, tested in safari lion osx :)
Good Link: [1] How to allow only numeric (0-9) in HTML inputbox using jQuery?
code
$(".hulk").keyup(function(){
this.value = this.value.replace(/[^0-9\.]/g,'');
});
html
<input type="text" class="hulk" value="" />
Update for copy paste stuff
$(".hulk").keyup(function(){
this.value = this.value.replace(/[^0-9\.]/g,'');
});
$(".hulk").bind('input propertychange', function() {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
code from another demo
$(".hulk").bind('input propertychange', function(event) {
if( !(event.keyCode == 8 // backspace
|| event.keyCode == 46 // delete
|| (event.keyCode >= 35 && event.keyCode <= 40) // arrow keys/home/end
|| (event.keyCode >= 48 && event.keyCode <= 57) // numbers on keyboard
|| (event.keyCode >= 96 && event.keyCode <= 105)) // number on keypad
) {
event.preventDefault(); // Prevent character input
}
this.value = this.value.replace(/[^0-9\.]/g,'');
});
this will allow both int.
it also removes text if user copy and paste with mouse.
$(document).ready(function () {
$('#textfield').bind('keyup blur', function (e) {
if (e.type == 'keyup') {
if (parseInt($(this).val()) != $(this).val()) {
$(this).val($(this).val().slice(0, $(this).val().length - 1));
}
} else if (e.type == 'blur') {
$(this).val('');
}
});
});
How can I cancel the keydown of a specific key on the keyboard, for example(space, enter and arrows) in an HTML page.
If you're only interested in the example keys you mentioned, the keydown event will do, except for older, pre-Blink versions of Opera (up to and including version 12, at least) where you'll need to cancel the keypress event. It's much easier to reliably identify non-printable keys in the keydown event than the keypress event, so the following uses a variable to set in the keydown handler to tell the keypress handler whether or not to suppress the default behaviour.
Example code using addEventListener and ignoring ancient version of Opera
document.addEventListener("keydown", function(evt) {
// These days, you might want to use evt.key instead of keyCode
if (/^(13|32|37|38|39|40)$/.test("" + evt.keyCode)) {
evt.preventDefault();
}
}, false);
Original example code from 2010
var cancelKeypress = false;
document.onkeydown = function(evt) {
evt = evt || window.event;
cancelKeypress = /^(13|32|37|38|39|40)$/.test("" + evt.keyCode);
if (cancelKeypress) {
return false;
}
};
/* For pre-Blink Opera */
document.onkeypress = function(evt) {
if (cancelKeypress) {
return false;
}
};
Catch the keydown event and return false. It should be in the lines of:
<script>
document.onkeydown = function(e){
var n = (window.Event) ? e.which : e.keyCode;
if(n==38 || n==40) return false;
}
</script>
(seen here)
The keycodes are defined here
edit: update my answer to work in IE
This is certainly very old thread.
In order to do the magic with IE10 and FireFox 29.0.1 you definitely must do this inside of keypress (not keydown) event listener function:
if (e.preventDefault) e.preventDefault();
jQuery has a nice KeyPress function which allows you to detect a key press, then it should be just a case of detecting the keyvalue and performing an if for the ones you want to ignore.
edit:
for example:
$('#target').keypress(function(event) {
if (event.keyCode == '13') {
return false; // or event.preventDefault();
}
});
Just return false. Beware that on Opera this doesn't work. You might want to use onkeyup instead and check the last entered character and deal with it.
Or better of use JQuery KeyPress
I only develop for IE because my works requires it, so there is my code for numeric field, not a beauty but works just fine
$(document).ready(function () {
$("input[class='numeric-field']").keydown(function (e) {
if (e.shiftKey == 1) {
return false
}
var code = e.which;
var key;
key = String.fromCharCode(code);
//Keyboard numbers
if (code >= 48 && code <= 57) {
return key;
} //Keypad numbers
else if (code >= 96 && code <= 105) {
return key
} //Negative sign
else if (code == 189 || code == 109) {
var inputID = this.id;
var position = document.getElementById(inputID).selectionStart
if (position == 0) {
return key
}
else {
e.preventDefault()
}
}// Decimal point
else if (code == 110 || code == 190) {
var inputID = this.id;
var position = document.getElementById(inputID).selectionStart
if (position == 0) {
e.preventDefault()
}
else {
return key;
}
}// 37 (Left Arrow), 39 (Right Arrow), 8 (Backspace) , 46 (Delete), 36 (Home), 35 (End)
else if (code == 37 || code == 39 || code == 8 || code == 46 || code == 35 || code == 36) {
return key
}
else {
e.preventDefault()
}
});
});
I want to make a text box allow only letters (a-z) using jQuery.
Any examples?
<input name="lorem" onkeyup="this.value=this.value.replace(/[^a-z]/g,'');">
And can be the same to onblur for evil user who like to paste instead of typing ;)
[+] Pretty jQuery code:
<input name="lorem" class="alphaonly">
<script type="text/javascript">
$('.alphaonly').bind('keyup blur',function(){
var node = $(this);
node.val(node.val().replace(/[^a-z]/g,'') ); }
);
</script>
Accepted answer
The accepted answer may be short, but it is seriously flawed (see this fiddle):
The cursor moves to the end, no matter what key is pressed.
Non-letters are displayed momentarily, then disappear.
It is problematic on Chrome for Android (see my comment).
A better way
The following creates an array of key codes (a whitelist). If the key pressed is not in the array, then the input is ignored (see this fiddle):
$(".alpha-only").on("keydown", function(event){
// Allow controls such as backspace, tab etc.
var arr = [8,9,16,17,20,35,36,37,38,39,40,45,46];
// Allow letters
for(var i = 65; i <= 90; i++){
arr.push(i);
}
// Prevent default if not in array
if(jQuery.inArray(event.which, arr) === -1){
event.preventDefault();
}
});
Note that this allows upper-case and lower-case letters.
I have included key codes such as backspace, delete and arrow keys. You can create your own whitelist array from this list of key codes to suit your needs.
Modify on paste only
Of course, the user can still paste non-letters (such as via CTRL+V or right-click), so we still need to monitor all changes with .on("input"... but replace() only where necessary:
$(".alpha-only").on("input", function(){
var regexp = /[^a-zA-Z]/g;
if($(this).val().match(regexp)){
$(this).val( $(this).val().replace(regexp,'') );
}
});
This means we still have the undesired effect of the cursor jumping to the end, but only when the user pastes non-letters.
Avoiding autocorrect
Certain touchscreen keyboards will do everything in their power to autocorrect the user wherever it deems necessary. Surprisingly, this may even include inputs where autocomplete and autocorrect and even spellcheck are off.
To get around this, I would recommend using type="url", since URLs can accept upper and lower case letters but won't be auto-corrected. Then, to get around the browser trying to validate the URL, you must use novalidate in your form tag.
To allow only lower case alphabets, call preventDefault on the event object if the key code is not in the range 'a'..'z'. Check between 65..90 or 'A'..'Z' too if upper case should be allowed.
Or, alternatively use one of the many input mask plugins out there.
See example.
$(<selector>).keypress(function(e) {
if(e.which < 97 /* a */ || e.which > 122 /* z */) {
e.preventDefault();
}
});
// allow only Alphabets A-Z a-z _ and space
$('.alphaonly').bind('keyup blur',function(){
var node = $(this);
node.val(node.val().replace(/[^A-Za-z_\s]/,'') ); } // (/[^a-z]/g,''
);
// allow only Number 0 to 9
$('.numberonly').bind('keyup blur',function(){
var node = $(this);
node.val(node.val().replace(/[^0-9]/,'') ); } // (/[^a-z]/g,''
);
Demonstrated below to allow only letters [a-z] using Jquery:
$(function() {
$('#txtFirstName').keydown(function(e) {
if (e.shiftKey || e.ctrlKey || e.altKey) {
e.preventDefault();
} else {
var key = e.keyCode;
if (!((key == 8) || (key == 32) || (key == 46) || (key >= 35 && key <= 40) || (key >= 65 && key <= 90))) {
e.preventDefault();
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<input id="txtFirstName" value="">
Solution described by #dev-null-dweller is working absolutely.
However, As of jQuery 3.0, .bind() method has been deprecated. It was superseded by the .on() method for attaching event handlers to a document since jQuery 1.7, so its use was already discouraged.
Check deprecated methods list for jQuery 3.0 here: http://api.jquery.com/category/deprecated/deprecated-3.0/
So the solution is to use .on() method instead .bind().
If you need to bind existing elements then the code will be :
$('.alphaonly').on('keyup blur', function(){
var node = $(this);
node.val( node.val().replace(/[^a-z]/g,'') );
});
If you need to bind to dynamic elements the code will be :
$(document).on('keyup blur', '.alphaonly', function(){
var node = $(this);
node.val(node.val().replace(/[^a-z]/g,'') );
});
You need to bind the event to document or some other element that already exist from the document load.
Hope this is helpful for new version of jQuery.
$("#test").keypress(function(event){
var inputValue = event.charCode;
//alert(inputValue);
if(!((inputValue > 64 && inputValue < 91) || (inputValue > 96 && inputValue < 123)||(inputValue==32) || (inputValue==0))){
event.preventDefault();
}
});
$("#test1").keypress(function(event){
var inputValue = event.charCode;
//alert(inputValue);
if(!((inputValue > 47 && inputValue < 58) ||(inputValue==32) || (inputValue==0))){
event.preventDefault();
}
});
$("#test3").keypress(function(event){
var inputValue = event.charCode;
//alert(inputValue);
if(!((inputValue > 64 && inputValue < 91) || (inputValue > 96 && inputValue < 123)||(inputValue==32)||(inputValue > 47 && inputValue < 58) ||(inputValue==32) || (inputValue==0))){
event.preventDefault();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
For letters:<input type="text" id="test"> <br>
<br>
For Numbers: <input type="text" id="test1">
<br>
<br>
For Alphanumeric: <input type="text" id="test3">
Thanks to the first answer.. made this..
<input name="lorem" class="alpha-only">
<script type="text/javascript">
$(function()
{
$('.alpha-only').bind('keyup input',function()
{
if (this.value.match(/[^a-zA-Z áéíóúÁÉÍÓÚüÜ]/g))
{
this.value = this.value.replace(/[^a-zA-Z áéíóúÁÉÍÓÚüÜ]/g, '');
}
});
});
</script>
This has some improvements like letters with accents, and changing "blur" for "input" corrects the Non-letters displayed momentarily, also when you select text with the mouse and dragging is corrected..
JQuery function to allow only small and Capital Letters:
Text Field:
<input id="a" type="text" />
JQuery Function:
$('#a').keydown(function (e) {
if (e.ctrlKey || e.altKey) {
e.preventDefault();
} else {
var key = e.keyCode;
if (!((key == 8) || (key == 32) || (key == 46) || (key >= 35 && key <= 40) || (key >= 65 && key <= 90))) {
e.preventDefault();
}
}
});
Supports backspace:
new RegExp("^[a-zA-Z \b]*$");
This option will not check mobile. So you can use a jQuery Mask Plugin and use following code:
jQuery('.alpha-field, input[name=fname]').mask('Z',{translation: {'Z': {pattern: /[a-zA-Z ]/, recursive: true}}});
$("#txtName").keypress(function (e) {
var key = e.keyCode;
if ((key >= 48 && key <= 57) || (key >= 33 && key <= 47) || (key >= 58 && key <= 64) || (key >= 91 && key <= 96) || (key >= 123 && key <= 127)) {
e.preventDefault();
}
var text = $(this).val();
$(this).val(text.replace(" ", " "));
});
if (!isValidName(name)) {
//return fail message
} else {
//return success message
}
function isValidName(name) {
var regex = new RegExp("^[a-zA-Z ]+$");
if (regex.test(name)) {
return true;
} else {
return false;
}
}