I'm using Twitter Bootstrap (v3) and I want to make a money input, where I can enter an amount of money with a fixed currency (currently €).
The input type needs to be type="number" because of how I want the input to look on mobile devices (not a big QWERTY keyboard, just numbers), but I do want to allow multiple patterns.
I think the way to go is with the .on("input", callback) method, but I'm not sure how to accomplish this.
I have tried the following:
$(document).ready(function() {
$("#amount").on("input", function() {
// allow numbers, a comma or a dot
$(this).val($(this).val().replace(/[^0-9,\.]+/, ''));
});
});
(for the HTML and CSS, see the jsfiddle link)
But obviously that doesn't work, otherwise I wouldn't be posting here. Whenever you try to type something invalid, the whole string disappears.
http://jsfiddle.net/bjcayhzb/1/
Explanation rather than (or alongside) a working example highly is appreciated.
It is the type of input field 'number' that comes in the way. It has its own keyup/input handler attached (modern browsers deal with it via JS code too) and seems to break things.
If you use
<input type="text" required="" placeholder="42,00" class="form-control" id="amount" />
then this works:
$(document).ready(function() {
$("#amount").on("input", function() {
// allow numbers, a comma or a dot
var v= $(this).val(), vc = v.replace(/[^0-9,\.]/, '');
if (v !== vc)
$(this).val(vc);
});
});
The only drawback of this approach is that if you try to put bad character in the middle of the string, cursor jumps to the end. And, of course, you can type multiple dots and commas.
Better approach would be to keep last good value stored in data and test the whole string and replace if new character invalidates match for the whole string.
Update
When input type="number" value contains non-number, jQuery val() returns empty string. This is why your code is not working. If "number" is a must (e.g. for numeric mobile keyboard), an approach would be to keep last known correct val() and put it back into control.
Related
I am trying to make a quick function for currency masking without the use of a jquery plugin. The environment I am in is using requirejs and any attempt to add plugins typically results in this problem:
MISMATCHED ANONYMOUS DEFINE() MODULES
Regardless, here is my code below, I am trying to get rid of the 3rd digit after the decimal so that there is only 2 digits after the decimal but for the life me can't figure out why nothing I'm doing is making it go away.
currencyMask("#test");
function currencyMask(fieldID) {
$(fieldID).on('keypress click', function() {
if (this.value != '') {
if (this.value.length == 1) {
this.value = '0' + this.value
}
this.value = parseFloat(this.value.replace(/[^\d]/g, '').replace(/(\d\d?)$/, '.$1')).toFixed(2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,').replace(/(\d{2})(\d$)/, '$1');
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id='test'>
After some discussion, some testing, and a bit of research. I changed my code a bit and resolved the issue as mentioned by Kevin B about keyup vs keypress.
After some research it appears the keypress triggers when "The key is pressed down" while
keyup is triggered when "The key is released". -W3 Schools
Because of that, I opted for keyup instead.
In addition, Kevin B said:
What makes the whole thing weird is that you're typing at the last position the moment your code does anything to the input because you're entirely replacing the value.
So I changed the code so that the user is typing at the beginning instead of the end. He also mentioned:
Regardless of how you change the value, if you're changing it at all while the input is still focused, it impacts the usability of the input because it will change the insertion point in one way or another. I prefer changing it after the fact rather than live as to not interfere with the user's input. for example, on blur.
This part here is definitely preference. I brought an admin over to my desk just now and asked which one they liked more. Most of them don't like ones that change after the fact. They find it confusing and to them, the whole point of the currency mask is to clearly see what they are typing as they are typing it.
To be clear, there isn't a 'wrong' way to do it. You can do .blur instead and that works too. This is more about what our specific users prefer.
Here is my updated code below:
currencyMask("#test");
function currencyMask(fieldID) {
$(fieldID).keyup(function() {
if (this.value != '' && this.value.length >= 3) {
this.value = this.value.replace(/[^\d]/g, '').replace(/(\d{2}$)/, '.$1').replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id='test'>
I've avoided asking this question here as I know many have in the past. I've spent some time during the last few days trying to find a solution/figure out how the toFixed() method works. I've read a lot of questions on this site and tutorials on others but I'm still not getting it.
I have several text fields with the class, ".entry". A dollar amount is supposed to go here. When people type the following (examples):
1.2
5
6.35
8.
I need them to change to:
1.20
5.00
6.35
8.00
In other words, add the trailing zeros. I know this is accomplished through the toFixed() method but I'm completely at a loss. I can't get it to work.
I have a script I found that totals all the text fields in a DIV elsewhere on the page and I notice that it uses the toFixed() method:
$("#total").html(sum.toFixed(2).replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1,'));
}
I tried using that same code here so the zeros could display in the text field:
$('.entry').keyup(function(){
var str = this.value.replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1');
if (str!=this.value) this.value = str;
});
It doesn't work.
I'm new to Jquery and Javascript so I realize I'm probably missing something obvious. Most of the tutorials I've read set the variable in the code and then use "document.write" to display the variable with the correct number of zeros:
Example:
document.write( 1.1.toFixed(2) + '<br>' );
But this isn't what I'm looking for. I need it to show up in the text field.
Thanks in advance!
A few things:
Use the change event instead of keyup. If you use keyup, the text wil change every time the user tries to type something, which is an annoying user experience.
Consider using an input of type number with a step of 0.1.
With those in mind, I'd do something like this:
$('.entry').change(function(){
// parse the typed value as a floating point number
var num = parseFloat(this.value);
// ensure there are two decimal places
this.value = num.toFixed(2);
});
Note that if the user types something with more than two decimal places, the value will be rounded.
Example: http://jsfiddle.net/jndt1e02/
Right now my app offers certain functionality, which involves browsing through html for specific inputs. Those input have id's which are based on some information user provides. So if in, lets call it input1, user gives us "first", we gonna have
<input id="first">
somewhere in html.
Later on javascript needs to find this input basing only on "first" string, it is fairly easy with jquery and coffeescript:
query = "first"
$("#" + query)
Works like a charm!
Problems start when query is a composed of two words, like "first input". This time unfortunately, code i provided is not going to work. What should i do to improve it?
id values cannot contain a space, so you can't have an input with the id "first input", it's invalid HTML. That's almost the only rule HTML imposes on id values. (CSS imposes more unless you use escaping.)
Since it's invalid, a browser is free to do what it likes — it could use only the first word and ignore the second, it could use the whole thing, it could throw out the id entirely, etc.
In practice, Chrome at least allows the invalid ID, and you can use an attribute selector to match it: Live Example
// Don't do this, even if it works in some browsers
var query = "first input";
$("[id='" + query + "']");
Note the quotes around the value, you need them because of the space.
But again, those id values are invalid and browsers are not obligated to handle them correctly. You might consider replacing the spaces with dashes, e.g. <input id="first-input">.
That problem is caused by jquery naming rule. "$("#first query")" cannot be recognised. You can use "_" to replace the space between the words.
Strictly, $("#first query") can be recognized, but it gets the tag whose id is first, and tag is "query". Anyway, it hardly can be found.
It's fairly simple, use attribute selector:
<input id="first second">
Javascript:
var query = "first second";
alert($("[id='" + query + "']"));
working fiddle (updated) here
How do I prevent the user from changing a string in an input box if the combined value of that input with their latest keypress does not pass a regular expression?
I see all kinds of examples on how to use keypress for testing individual characters, but I need to match the entire value to a regular expression, not just the key they pressed.
For example, The textbox needs to conform to the following regular expression:
"^023-[0-9]{0,7}$"
So if they want to change "023" to "23", it should stop them when they delete the 0 character. The same is true for deleting the - after 023. It should also stop them once they enter more than 7 numbers after 023. This cannot be done on blur. It must be done after every key stroke. Performance is not an issue.
If I use keypress() event in jQuery, and get the value of the input element like this:
$(this).val()
Then I will only get the value before they pressed the key - not after. Thus, there is no way to test the input against my regular expression. I cannot simply append the key pressed to this string, because I cannot make the assumption that they are only entering keys at the right-most side of the string.
I have looked into keydown/keyup events, and while keyup seems to give me the current value of the input after the user has pressed a key, I am finding it difficult to remove the effects of what they typed... which keypress() does not have a problem with apparently.
var regex = new RegExp("^023-[0-9]{0,7}$");
$("#number").keyup(function(event) {
var number = $(this).val();
if(!regex.test(number)) {
event.preventDefault();
return false;
}
});
The above code just doesn't work. It seems keypress() gives me the ability to stop what they typed, but keyup gives me the ability to get the current value. I need a solution that does both ;)
The problem really stems from the fact that the browser has no MVC architecture. The model is the view. Unfortunately, we can't validate the updated model before the view is updated... because we need the view updated during a keyup event to get the updated model data... and by then, it's too late to prevent them from updating the view since it's already been updated.
How about this:
var prevValue = "";
$("#number").keydown(function(e) {
prevValue = $(this).val();
});
$("#number").keyup(function(e) {
...
if(!regex.test(number))
$(this).val(prevValue);
// show error or other processing you need to do
});
try this:
var pattern = new RegExp("^023-[0-9]{0,7}$");
$("#number").change(function(e){
if (!pattern.test($(this).val())) {
return false
}
})
The event parameter that you have will contain all the details of the event that you are handling. This will include the key that was pressed.
Of note is that keydown and keyup events will return the key pressed, while keypress will return which character is entered which may be better for your choice.
See the help page here: http://api.jquery.com/keypress/ for more details.
In summary though event.which should do what you want. You can combine that with the original value of the textbox and from that get the new value. If it isn't valid then cancel the event, if it is valid then let it go...
If you can use the jQuery Validate plug-in, you can create a custom validator to match your RegEx. Then all you have to do is map the validator to that input. You'll still have to validate on the server-side, but you're probably already doing that.
To do what you want, the jquery caret plugin is required. Please note that you'll need to remove the comments from the beginning of the file (or at least move them) or the byte order mark at the start of the code will cause an error.
So, what you need to do is capture the keypress, insert the character at the correct place in the string, check if that new string is valid and then either show the new insertion or not. I think the following does what you need:
$(document).ready(function(){
var regex = new RegExp("^023-[0-9]{0,7}$");
var caretpos;
$('#number').keypress(function(event){
// get the caret position
caretpos = $(this).caret().start;
//split the current value according to where the caret is
valuestart = $(this).val().substring(0,caretpos);
valueend = $(this).val().substring(caretpos);
// insert the fired character into the string
valuetocheck = valuestart + String.fromCharCode(event.which) + valueend;
// check if the proposed new value passes the regex
if (!regex.test(valuetocheck)) {
// failed, prevent the character being shown
event.preventDefault();
}
});
});
I've tested this in the latest versions of FF, Chrome, Safari, Opera and IE9. In FF and Opera, cursor key presses are completely ignored while they move the caret as usual in the other browsers so you may want to add some code to ensure consistent behaviour for that. You may also want to add some code to handle what will happen if the user selects some characters rather than just clicking into the input. The jquery caret plugin has usage examples for selections.
I want a Javascript validation that allows maximum of 3 commas in a text field user to enter a number or text in format
123,456,789,0000
meaning 3 Commas(,) are allowed, there could be any number of digits/letters between commas. User may choose to enter only 2 Commas i.e. 3 values but max number of Commas that would be allowed are 3
for eg
a,bb,ddddd,eeeee (4 tags)
a,cc,bbbbb (3 tags)
What I am trying to achieve is user is allowed to enter only 4 comma separated tags thus making sure user cannot flood the article with 100's of tags
var txt = '123,456,789,0000';
if( /^([^,]*,){0,3}[^,]*$/.test( txt ) ){
// good
}else{
// bad
}
change the * to a + if you want to ensure that there aren't two commas in a row, e.g.: 12,,345
If you have control on server side, I suggest doing the validation there.
Because If you try to do the validation on the client using java script, it can be circumvented by either turning off java Script all together, or using Firefox's FireBug extension by manipulating or manually executing a request, bypassing your java script validation altogether.
But if you really still want to do some kind of validation in javascript, you can do something like the following:
Given this input field <input id="txtInput" type="text" />
You could bind a keyup event (pay attention to people attempting to paste from the clipboard, keyup will not catch it if they do it via context menu)
$('#txtInput').keyup(function(){
//This splits up the string value of the text box into an array
//wherever a coma appears
var tags = $(this).val().split(',');
//These would be your tags, without the coma, count them to find out how many
//the user tried to enter.
if (tags.length > 4)
alert('there is more than 4 tags');
});
Of course this is only an example, but you could adapt the idea to your needs. You don't have to bind this to the keyup event, you could bind this to a click event on the submit button or something, it all depends on your needs.