Checking if Text Input Pattern is Valid Using JavaScript - javascript

The desired effect is such that when the user types in any character that is not a letter or a number, that character is immediately removed; thus causing the text cursor to not advance.
After already trying to look for solutions online myself, here is what I have so far:
<input type="text" id="job-name" maxlength="20" pattern="[a-zA-Z0-9]+" style="width:200px; text-align:center;">
document.getElementById('job-name').addEventListener('keydown', function () {
if (!document.getElementById('job-name').validity.valid) {
var text = document.getElementById('job-name').value;
text = text.slice(0,-1);
document.getElementById('job-name').value = text;
}
});
The problem is that the check of the 'valid' attribute is thus far always true and never false, regardless of the character typed in, for some reason. My expectation was that whenever the character that was just typed in does not conform to the pattern, the 'valid' should return false; otherwise, it is true.

Use the event input to accomplish that:
This approach uses the regex /[^a-z0-9]+/i.
Basically, for every input char/text, the handle will replace with empty the invalid char.
document.getElementById('job-name').addEventListener('input', function(e) {
this.value = this.value.replace(/[^a-z0-9]+/i, '');
})
<input type="text" placeholder='Paste text, drag text or type text' id="job-name" maxlength="20" style="width:400px; text-align:center;">

Try using the input event instead of keydown.
document.getElementById('job-name').addEventListener('input', function () {
if (!document.getElementById('job-name').validity.valid) {
var text = document.getElementById('job-name').value;
text = text.slice(0,-1);
document.getElementById('job-name').value = text;
}
});

Related

checkValidity / reportVality not working for values set via code

The HTML5 checkValidity() / reportValidity() methods don't seem to work if values are set via JavaScript.
Consider this example (JSFiddle):
<input id="text-field" maxlength="3" placeholder="Max len: 3 chars" />
<button id="set-field-value">Set</button>
<button id="check-valid">Is valid?</button>
<script>
window.onload = function() {
var textField = document.getElementById('text-field');
document.getElementById('set-field-value').onclick = function() {
textField.value = 'This is a very looooooooooooooooooooooooooooooong text';
};
document.getElementById('check-valid').onclick = function() {
window.alert(textField.checkValidity());
};
};
</script>
If you click the Set button, the value of the input field is set to an invalid value (it's length is greater that 3 characters), but the checkValidity() method still says that the input is valid (checked on Chrome, Edge and Firefox).
Why? Is there a way to determine is the field is valid even if its value is set via code?
I investigated this a while. It seems that you're at least missing <form> wrapping the input + button content.
But still, even if I tried to set input field required, still the ValidityObject won't notice that length is exceeded.
As a semi-workaround, I came with an idea of using pattern property:
<input id='textfield' pattern='\S{0,3}'>
(= \S stands for 'all characters except spaces')
This at least will prevent for content beyond three characters. In addition, you can have a setCustomValidity message for invalid cases.
See working example at: https://codepen.io/zvona/pen/rNavqxP?editors=1010
I've tried a few things that led me to understand that checkValidity does not check the value itself.
When I click on #check-validity I get :
textField.validity.tooLong // false
textField.validity.valid // true
textField.value // This is a very looooooooooooooooooooooooooooooong text
When I type myself in the input, my browser does not let me type more than 3 characters.
Why?
Precisely I don't know, but there is this awesome article on constraint validation that is worth having a look.
Is there a way to determine is the field is valid even if its value is
set via code?
textField.value returns your string, you can then access it's length. In this context, I would have anyway prefered this way.
const tooLong = textField.value.length > 3;
if (tooLong) window.alert('Something');
I hope it helps.
You should check if the form valid not the input. BUT it seems that the maxLength attribute is not something that trigger validation at all...
If you want to check length of input text you can do that with this:
window.onload = function() {
var textField = document.getElementById('text-field');
document.getElementById('set-field-value').onclick = function() { textField.value = 'ab'; };
document.getElementById('check-valid').onclick = function() {
if (textField.value && // if exist AND
textField.value.length > 2 && // if value have 3 charecter at least
textField.value.trim().length > 2 // if value is not just spaces
) {alert ('input OK');} // alert that input ok
else { alert('please insert at least 3 charecters');} // else alert error
};
};
<form id="formCheck">
<input type="text" id="text-field" min="3" />
<button type="button" id="set-field-value">Set</button>
<button type="button" id="check-valid">Is valid?</button>
</form>
The checkValidity() method works as expected on this example (using input number and min attribute) though:
window.onload = function() {
var theForm = document.getElementById('formCheck');
var numberField = document.getElementById('number-field');
document.getElementById('set-field-value').onclick = function() { numberField.value = '2'; };
document.getElementById('check-valid').onclick = function() {
window.alert(theForm.checkValidity());
};
};
<form id="formCheck">
<input type="number" id="number-field" min="3" />
<button type="button" id="set-field-value">Set</button>
<button type="button" id="check-valid">Is valid?</button>
</form>

forcing focus to remain on a form text element until the value is numeric

I have a form which has input fields that expect numbers only.
I'm using javascript to validate the form when the value of the field changes.
If the value is numeric, do nothing.
If the value is not numeric, set it to zero and put focus in that text field. Essentially, I'm trying to trap the cursor in that field until a numeric value is entered. For some unknown reason, focus is not being placed on that form element. cell.focus() does not work. I've even tried document.getElementById(cel.getAttribute("ID")).focus(); What might I be doing wrong?
<html>
<head>
<script>
function NAN(cell){
if (cell.value != "") {
var re = /^(0|[1-9][0-9]*)$/;
if (re.test(cell.value) == false) {
alert('You must supply a numeric value greater than 0.');
cell.value = "0";
cell.focus();
}
}
}
</script>
</head>
<body>
<input type="text" name="num" value="" onchange="NAN(cell)"/>
</body>
</html>
Your problem is in the onchange attribute:
<input type="text" name="num" value="" onchange="NAN(cell)"/>
The value is executed as JavaScript code directly. You're passing code, not just a generic signature or prototype.
Inside those event handler snippets, there's a special object this defined, referring to the current DOM element (the input tag in this example).
(Just to mention it, there is also a second predefined object event, which most likely caused your confusion.)
As a simple fix for your issue, replace cell with this in the call and it should work:
<input type="text" name="num" value="" onchange="NAN(this)"/>
It's also important to note that you should keep in mind that this verification requires JavaScript to be executed. If it's disabled, the user might still pass any values, so you should check the value server side as well (assuming this isn't just client-only code).
As an alternative to using JavaScript, you could just use HTML5 to force a specific pattern on inputs. In this case this would be trivial to do:
<input type="text" name="num" value="" pattern="(?!0)\d+" title="Quantity">
The user won't be able to submit the form unless the pattern is validated, so there's no need to force the input focus. The pattern always has to match the full value, from beginning to the end. The title attribute is typically used to provide more information in the error popup.
There are two things done:
You have to change cell to this with onchange.
According to this question at least with Firefox setTimeout has to wrap this focus-method so that it works as expected.
And a more user-friendly approach is inserted as well at the second input-field.
Hope this example helps you:
function NAN(cell) {
if (cell.value != '') {
var re = /^(0|[1-9][0-9]*)$/;
cell.value = cell.value[0]=='0'?+cell.value:cell.value;
if (re.test(cell.value) == false) {
alert('You must supply a numeric value greater than 0.');
cell.value = '0';
setTimeout(function () {
cell.select();
cell.focus();
}, 0);
}
}
}
/*
* a more user friendly approach
*/
function NAN2(cell) {
if (cell.value != '') {
var re = /^(0|[1-9][0-9]*)$/;
cell.value = cell.value[0]=='0'?+cell.value:cell.value;
if (re.test(cell.value) == false) {
alert('You must supply a numeric value greater than 0.');
cell.value = '0';
setTimeout(function () {
cell.select();
cell.focus();
markElement(cell);
}, 0);
}
else{
tickElement(cell);
}
}
}
function tickElement(cell){
cell.setAttribute('style','border: 1px solid green');
}
function markElement(cell){
cell.setAttribute('style','border: 1px solid red');
}
<p>
Your approach(onchange):
<input type="text" name="num" value="" onchange="NAN(this)"/>
</p>
<p>
Or you can use a more user friendly approach to notify an user right now when they are tipping something wrong (onkeyup):
<input type="text" name="num" value="" onkeyup="NAN2(this)"/>
</p>

Allow only roman characters in text fields

I am finding a way to make all the text boxes in the website only accept roman characters. Is there any easy way to do it globally.
Thanks in advance.
In modern browsers <input> accepts an attribute called pattern. This allows to restrict the valid characters in a given field.
input:invalid {
background-color:red;
}
<form>
<input type="text" pattern="[a-zA-Z\s\.\-_]+" />
<button type="submit">Submit</button>
</form>
For all other browsers you can find all form field via jQuery, check if a pattern-attribute exists, and check it against the value of a given field. You may also replace disallowed characters:
$('form').on('keyup blur','input',function() {
if ($(this).val() && $(this).attr('pattern')) {
//var pattern = new RegExp('^'+$(this).attr('pattern')+'$', 'g');
//$(this).toggleClass('invalid', pattern.match(!$(this).val()));
var pattern = new RegExp($(this).attr('pattern').replace(/\[/,'[^'), 'g');
$(this).val($(this).val().replace(pattern,''));
}
});
input:invalid {
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<form>
<input type="text" pattern="[a-zA-Z\s\.\-_]+" />
<button type="submit">Submit</button>
</form>
Oh, you still want to validate form inputs on the server-side. All HTML- or Javascript-stuff does not prevent all visitors of your site to submit broken stuff.
I will refer to the marked answer for the following question for the regex which filters out non-roman characters:
How to detect non-roman characters in JS?
Spoiler: the regex is /[^\u0000-\u024F\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF]/g
Now all you need is a little bit of tinkering with jQuery:
var myInputId = "#foo"; // Or whatever you wish to use.
var input = $(myInputId);
var exp = /[^\u0000-\u024F\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF]/g;
input.blur(function() {
input.value = input.value.replace(exp, "");
});
Include this snippet into your master page for example:
<script>
$(function(){
$('input[type=text],textarea').keypress(function(e){
var char = String.fromCharCode(e.which || e.charCode);
var rgx = /[\u0000-\u007F]/;
if (rgx.test(char) == false)
return false;
})
})
</script>
Here is my idea based on #fboes answer.
I also needed to show user whats wrong, so there is error message showing but with no redundancy when typing couple of forbidden characters in a row.
//I wanted first to assign pattern attr to every input in form but when it's happening, all "\" chars are removed from regex therefore - it doesn't work, so I had to add it in templates for every input.
let isIncorrect = false;
scope.checkPattern = function(e) {
// I don't want to allow Chineese, cyrylic chars but some other special - yes
var pattern = new RegExp('[a-zA-Z\s\.\-_äÄöÖüÜßąćęłńóśźżĄĆĘŁŃÓŚŹŻ]+', "g");
if ($(e).is(':valid')){
return true
} else {
$(e).val($(e).val().replace(pattern,''));
return false
}
};
scope.removeAlert = function (e){
$(e).parent().find('.text-danger').remove();
isIncorrect = false;
}
// unallowed characters in order inputs
$('.my-form').on('keyup blur','input',function(e) {
if (!scope.checkPattern($(this))) {
if (!isIncorrect){
// show this error message but only once (!) and for specified period of time
$(this).parent().append('<p class="text-danger">Only latin characters allowed</p>');
isIncorrect = true;
}
setTimeout(scope.removeAlert, 3000, $(this));
}
});

Jquery replace string in a textarea

I am trying to replace a string value in textarea while typing in textbox with jquery. I used keypress event to try achieving that. What may be the issue here in this fiddle?
<input type="text" id="textbox" />
<textarea id="txtArea">This is a sample test.</textarea>
jquery code
$("#textbox").keypress(function () {
var txtAreaValue = $('#txtArea').val();
var txtAreaValueAfterreplace = txtAreaValue.replace('sample', $(this).val());
$('#txtArea').val(txtAreaValueAfterreplace);
});
The main problem is that, when using keypress you are getting the value of the input box before it is set, so nothing appears. However even if you change it to keyup you still will only get one value because once 'sample' is replaced it is gone so therefor it cannot be replaced again.
A new logic needs to be considered if you are wanting to replace sample with the full value of the textarea. Consider the following example:
$("#add").click( function () {
$( '#txtArea' ).val( $('#txtArea').val().replace( 'sample', $("#textbox").val() ) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="textbox" /><br>
<input type='button' id='add' value='add'>
<textarea id="txtArea">This is a sample test.</textarea>
Or we replace when the user stopped typing
var typing;
$("#textbox").keyup( function () {
// Stop the change from being made since they typed again
clearTimeout(typing);
// They typed, so set the change to queue up in a 3rd of a second
typing = setTimeout(function(){
$( '#txtArea' ).val( $('#txtArea').val().replace( 'sample', $("#textbox").val() ) );
},350);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="textbox" /><br>
<textarea id="txtArea">This is a sample test.</textarea>
You want to look for keyup, not keypress (you want to make sure you get the whole string.
You are trying to put the textbox value right? You're looking for the textarea value in line two of the javascript.
If you replace sample on the first key stroke, there won't be anything to replace the second key stroke.
You can simplify lines 3 and 4 into one line.
replace can only be used on a string. So you need to get the value first, if you're going to do it that way. txtAreaValue.val().replace('sample', $(this).val());
Feel free to play around with it on this fiddle: http://jsfiddle.net/snlacks/abc6skp9/
$("#txtBox").on('keyup', function () {
var txtValue = $(this).val();
$('#txtArea').val("this is a " + txtValue);
});
If you have a longer string, replace might work better, but you still need to store the full string somewhere.
var longString = "some really long string... sample... more...";
$("#txtBox").on('keyup', function () {
var txtValue = $(this).val();
$('#txtArea').val(longString.replace('sample', txtValue);
});

Custom Validation on HTML Number Input Misbehaving

In putting together a small webapp, I'm trying to ensure that end users are unable to place invalid characters in a number field that can hold signed floats. I'm using Dojo to search on an applied CSS class (in this case, ogInputNumber) and set events on input, keyup, and blur.
Ideally, I would like the input to be type="number" and to only allow digits, a hyphen (for signed floats), and a period character to act as a decimal place. If a user includes more than one hyphen or period character, the JS should truncate that second invalid character and everything thereafter in the input. Unfortunately, the JS behaves differently depending on whether the input is type="number" or type="text".
For type="text", if I attempt to enter the text 2.6a, 2.6 is fine, but the a is caught on the input event and prevented from appearing in the input. This is the desired behavior, but I would like to have the input as type="number" so the number spinners appear and for ease of use with mobile devices (so the number keyboard is brought up by default).
For type="number", if I attempt to enter the text 2.6a, the 2.6 is allowed to remain, but as soon as a is typed, the entire field is cleared out. That will prevent any invalid characters, but it's annoyingly overzealous. I've replicated this behavior on Chrome, Firefox, IE11, and Opera.
Can anyone offer any suggestions as to why the JS operates differently between inputs with type="text" and those with type="number"?
HTML:
<p>
<label for="numberInput1">Text Input</label>
<input id="numberInput1" class="ogInputNumber" type="text" />
</p>
<p>
<label for="numberInput2">Number Input</label>
<input id="numberInput2" class="ogInputNumber" type="number" />
</p>
JS:
// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],
function (ready, on, query) {
query(".ogInputNumber").forEach(function (node) {
// Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
on(node, "input, keyup", function () {
this.value = this.value.replace(/[^\d\.-]/g, '');
});
// When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
on(node, "blur", function () {
try {
if (this.value) {
this.value = parseFloat(this.value).toString();
} else {}
} catch (error) {
this.value = 0;
}
});
});
});
Working JSFiddle: http://jsfiddle.net/etehy6o6/1/
I think that's the default behavior of number input type, but I'm not sure. It's logical to think the input should not let the user put anything that is not a number, so it clears all the value before you can fire your keyup event.
So to keep the last valid value declare a variable outside the scope of your event and set it to the replaced value that was not cleared because invalid key input.
Using the code in your Fiddle:
Edited because addressed bug in comments
HTML
<!-- I asigned default values to test other scenarios -->
<p>
<label for="numberInput1">Text Input</label>
<input id="numberInput2" class="ogInputNumber" type="text" value="3.1416" />
</p>
<p>
<label for="numberInput">Number Input</label>
<input id="numberInput" class="ogInputNumber" type="number" value="3.1416" />
</p>
Javascript
// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],
function (ready, on, query) {
query(".ogInputNumber").forEach(function (node) {
var validValue = this.value;
// Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
on(node, "input, keyup", function () {
if (this.value == '' && validValue.length > 1) {
this.value = validValue;
}
this.value = this.value.replace(/[^\d\.-]/g, '');
validValue = this.value;
});
// When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
on(node, "blur", function () {
try {
if (this.value) {
this.value = parseFloat(this.value).toString();
} else {}
} catch (error) {
this.value = 0;
}
});
});
});

Categories

Resources