regex in javascript allow only numbers and one dot followed by max 2 number
Asked Answered
F

5

5

With javascript I want to limit a contenteditable cell, to allow only numbers and one dot and after the dot max 2 number

valid examples:

  • 2
  • 0.2
  • 0.35
  • .5
  • .22
  • 4.55
  • 6.4
  • 6546545.55

in my exaple I

function onlyNumberAndADot(element) {
  const invalidChars = /\D/g;
  ob = element.target;
    if (invalidChars.test(ob.textContent)) {
      ob.textContent = ob.textContent.replace(invalidChars, "");
    }
}

document.getElementById("test1").addEventListener("input", function(event) {
  onlyNumberAndADot(event);
})
#test1 {
  border: 1px solid gray;
  padding: 5px;
  width: 100px;
}
<table class="table">
  <tbody>
    <tr>
      <td id="test1" contenteditable="true"></td>
    </tr>
  </tbody>
</table>

only in pure javascript I am trying this: [0-9]?(.+)?[0-9]{1,2} but its not okey and I dont know how to implement to my function

not a correct example... because of number 6546545.55

Feder answered 26/5, 2018 at 18:39 Comment(2)
what if you used <input id="meters" type="number" name="meters" step="0.01" min="0" >Darbydarce
I use contenteditable in a table, I dont want to use input, but thxFeder
C
4

Everytime your event handler runs, the input grows by one character, so I think a better approach would be to check if the input still matches your regex rule and, if not, restore the previous value and force it to blur().

Try to update your event handler like this and it should work:

let curValue = '';
function onlyNumberAndADot(event) {
  const valid = /^\d*\.?(?:\d{1,2})?$/;
  const text = event.target.textContent;  
  if (!valid.test(text)) {
    event.target.textContent = curValue;
    event.target.blur();
  } else {
    curValue = event.target.textContent;
  }
}

document.getElementById("test1").addEventListener("input", function(event) {
  onlyNumberAndADot(event);
});

document.getElementById("test1").addEventListener("blur", function(event) {
  event.target.textContent = event.target.textContent.replace(/\.$/,'');
});

I created a fiddle with this solution and it works.

Notice that you have to temporarily allow inputs like '0.', otherwise users won't be able to type in the dot, so I did another verification on blur event, to remove the final '.'

Craiova answered 26/5, 2018 at 20:18 Comment(7)
There i can insert alphabetic character what its not okFeder
you're right, one minute for me to fix the regex, please!Craiova
there, please, try it again @almostokey!Craiova
it deletes the last dot as well, when clicked second timeMetropolis
I tested, one example type "." then a number "6" and if you put the cursor between the number and the dot then you can type an alphabetical character ... I have to cover all possible wrong user input. Here is a nice example but I dont know to restrict the numbers after the dot (to enable only two) jsfiddle.net/xwbv4a1u/8Feder
Right, that's because the function only removes the last char, but it is not always the invalid one, as you pointed. To restore the original value before the key type you would need some variable to keep track of it. I'll update my answer with an example.Craiova
@GuilhermeLemmi with your regex I achieved what I required, now its working nice, without losing focus on typing not number: jsfiddle.net/rmn4updr/27Feder
G
3

This should cover all your cases.

/^(?:\d+(?:\.\d{1,2})?|\.\d{1,2})$/

Readable version

 ^ 
 (?:
      \d+ 
      (?: \. \d{1,2} )?
   |  \. \d{1,2} 
 )
 $

update after chat.

Seems the regex needs to operate on input in real time event handler,
like keypress paste etc..

To do that, it needs to be a progressive optional type of regex
to allow for partial matching, yet strip off invalid text.

That regex is
Find /^(\d+(?:\.\d{0,2})?|\.\d{0,2})?.*?$/
Replace "$1"

Readable version

 ^ 
 (                             # (1 start)
      \d+ 
      (?:
           \. 
           \d{0,2} 
      )?
   |  \. \d{0,2} 
 )?                            # (1 end)
 .*? 
 $

When submitting the current entry a final validation regex could
be necessary, but maybe not.

That regex is something like this ^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$

The only possible invalidation will only ever be a single dot, or a blank
which was a valid current input but not valid in the final.

If it doesn't match, just set the input to 0 and go from there.


update

To limit rewriting the input text on every event, add a couple
of extra filter steps in the handler.

var RxFinalForm = /^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/;
var RxRmvInvalid = /[^\d.]+/g;
var RxPartialForm = /^(\d+(?:\.\d{0,2})?|\.\d{0,2})?.*?$/;

function onlyNumber(element) { 
 ob = element.target; 
 var sContent = ob.textContent;

 // Test if the current content is a valid Final Form.
 // Note the ob.textContent does not need to be changed,
 // thus preserving the caret position.
 // -----------------------------------------------------
 if ( RxFinalForm.test( sContent ) )
    return;  // No need to change anything, just return

 // Remove any invalid characters ( non - dot/digit )
 // --------------------------------------------------
 sContent = sContent.replace( RxRmvInvalid, "" );

 // Extract the Partial Form
 // -------------------------
 sContent = sContent.replace( RxPartialForm, "$1");

 // Finally, if 'ob.textContent' does not equal 'sContent', change it.
 // This will happens when an extra dot was enterred.
 // ------------------------------------------------------------------
 if ( ob.textContent !== sContent )
    ob.textContent = sContent;
} 
Gaona answered 26/5, 2018 at 21:7 Comment(20)
can you help me with putting into a working example, this I cant get to work: jsfiddle.net/xwbv4a1u/9 This works but I cant restrict to enable only 2 number after the dot: jsfiddle.net/xwbv4a1u/8Feder
@almostokey - What part of the regex is giving you trouble ? regex101.com/r/vAUAwv/1Gaona
I think that regex is ok: regexr.com/3q3cq but I cant implement this to my example to make it work: jsfiddle.net/xwbv4a1u/9Feder
In this example there is a nice regex, but I cant figure out how to restrict to 2 number the numbers after the dot: jsfiddle.net/xwbv4a1u/8Feder
@almostokey - Oh, I think you have it backwards. It should be if ( ! invalidChars.test(ob.textContent) ) then set it to blank. This regex is a test for passing, not failing.Gaona
@almostokey - If you negate, how can it be the same thing. Try === NULL or some other form of negative testing. Better yet if (rx.test()) { /**don't do anything**/ } else { /** clear the buffer **/}Gaona
same thing = not working :D I think I missed something or I dont know, can you check the example above please?Feder
Try if (invalidChars.test(ob.textContent)) {} else ob.textContent = ""; But it should be named like this if (! validRx.test(ob.textContent)) ob.textContent = "";Gaona
In both the if and else you're clearing the string. Try this if (invalidChars.test(ob.textContent)) {} else { ob.textContent = ""; }Gaona
jsfiddle.net/xwbv4a1u/13 now only numbers can I inpu, no dot is permittedFeder
How do I run your sample prog ?Gaona
you have to click on left top to the Run and if it works, then to update and send the linkFeder
It's not playing nice with my IE11. Black screen, buttons on top not visible, just flyover hints. When I think I hit run, it doesn't do anything.Gaona
Let us continue this discussion in chat.Feder
this regex works, but in the contenteditable if i write 44443333 and between 4 and 3 I try to type an alphabet character then it will trim that 4444 part from the inputFeder
@almostokey - Added an update to filter the input. This should cover almost all possibilities, and is the most efficient way to do it.Gaona
here I maked your code to work, but it seems that I can enter more than 2 number after the dot jsfiddle.net/xwbv4a1u/23Feder
@almostokey - Paste error for RxPartialForm regex, added it. Oh, please don't post a fiddle link as I cannot run them from my browser.Gaona
yeahh, now it is correct, works perfect, I will paste the fiiddle if somebody want to see the demo, thank you jsfiddle.net/xwbv4a1u/26Feder
@almostokey - Oh good. I can't test it, but I can imagine it should work ok. I think this would be a template for all input box filter handlers - just a guess. I'm an old school MFC programmer, and know their behind the scenes props. Of course, the money is in the regex, where I make my living.Gaona
D
1

You could use a regular expression with a group for the dotted part.

/^[1-9]*\d?(\.\d{1,2})?$/

console.log(['2', '0.2', '0.35', '.5', '.22', '4.55', '6.4', '6546545.55', '-1', '0.', '00', '00.0', '.123'].map(s => /^[1-9]*\d?(\.\d{1,2})?$/.test(s)));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Delivery answered 26/5, 2018 at 19:17 Comment(4)
@nina just out of curiosity why the ? in your regex ?Caylacaylor
@AlexanderSolonik, because of the optional character of dot and following digits.Delivery
the problem is that if the verification runs at every character input, when he types '123.' the dot will cause the regex to fail (as there are no digits after the dot yet) and user will be blocked from inputing decimal digits. So this regex works best for me: ^[0-9]*\.?(?:\d{1,2})?$Craiova
@GuilhermeLemmi can you make this example to work with your regex? jsfiddle.net/xwbv4a1u/3Feder
C
0

Use word boundary to limit decimal:

[0-9]?\.?[0-9]{1,2}\b
//          here __^^

or better:

\b\d+(?:\.\d\d?)?\b
Counterweight answered 26/5, 2018 at 18:45 Comment(2)
second: regexr.com/3q3b7 so to test in real example this two I have to negate, but how?Feder
I cant set up to work this example with your regex: jsfiddle.net/xwbv4a1u/3Feder
M
0

You need to do it in multiple if else statements, because this is an input tag, and you are probably updating as soon as the user types on it.

So first: you need to test/match if it's only digits or it's a dot var digitsAndDot = /[0-9\.]$/ and do something about it, alternatively you can check if it's nonDigit except for dot /[^0-9\.]$/ do something with it.

Second: if the string already has a dot(.) /\./ than allow only type numbers.

Third: find if you don't want this "0.1.2." to appear var duplicate = /.\d{0,2}$/ and then do something, for example keep deleting the rest of the input for numbers (more than two) and don't allow more dots.

You could also turn the values into array and then manipulate it.

Metropolis answered 26/5, 2018 at 19:29 Comment(1)
I think its a nice resolution theory, but I have a real example where with one row you can make this jsfiddle.net/xwbv4a1u/8 only I have to restrict to two number the numbers after the dotFeder

© 2022 - 2024 — McMap. All rights reserved.