jquery run conditional validation inside .on - javascript

I have a form with the ID #primarySearch. It has 3 text inputs, all of which have their own ID as follows: #ecNumber, #casNumber, #substanceName.
I have the following js. If the user enters anything in a text input in #primarySearch it runs a function called processPrimarySearch and sends the appropriate input value to it:
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// Ignore tab key
if (e.which != 9) {
processPrimarySearch.call(this);
}
}
});
function processPrimarySearch() {
// ...
}
I've also got some other js (which is just inside document.ready) which stops the user entering anything other than numbers and dashes - but only in the #ecNumber and #casNumber fields (please note I adapted this from jQuery only allow numbers,letters and hyphens). Although this code fires if the user is entering things into these 2 fields, it also results in processPrimarySearch running irrespective of whether the user input is valid. This is because there is no connection between the code above, and the following code:
$('#ecNumber, #casNumber').keypress(function (e) {
var allowedChars = new RegExp("^[0-9\-]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (allowedChars.test(str)) {
return true;
}
e.preventDefault();
return false;
}).keyup(function() {
// the addition, which will check the value after a keyup (triggered by Ctrl+V)
// We take the same regex as for allowedChars, but we add ^ after the first bracket : it means "all character BUT these"
var forbiddenChars = new RegExp("[^0-9\-]", 'g');
if (forbiddenChars.test($(this).val())) {
$(this).val($(this).val().replace(forbiddenChars, ''));
}
});
The result of what's happening at the moment is that if a character was entered such as "z" in #ecNumber, the validation regex code will fire and stop the character "z" appearing in the input - good. However, processPrimarySearch() will also fire because it's defined inside the .on for any input in the #primarySearch form.
My problem:
What I want to do is run the validation regex inside my .on but only if it's the #ecNumber or #casNumber fields (#substanceName must not be validated here).
I've managed to write the following which uses an array to say which field the user is entering input on. Where I'm doing the console.log is where I need the validation regex to occur
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// Ignore tab key
if (e.which != 9) {
var arr = ["ecNumber", "casNumber"];
if ($.inArray($(this).attr('id'), arr)!== -1) {
console.log($(this).attr('id'));
}
processPrimarySearch.call(this);
}
}
});
What is the best way to do this? I'm unsure whether to move the code which does the regex into a function, and then call it (with .call?) or some other method? And are there any issues with this being asynchronous in nature?

It's all about program flow and how you want to handle it. Your problem is not really an async problem in the last way that you presented your code. Here is one solution (of many possible ones). I put some comments in the code to explain the basics.
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// if this is not the tab key and the input contains valid characters
if (e.which != 9 && isThisValid($(this), e)) {
processPrimarySearch.call(this);
}
else {
e.preventDefault();
}
}
});
function isThisValid($elem, event) {
var ids = ["ecNumber", "casNumber"], // ids to validate, everything else is valid
result = true; // default result
// is this one of the id's to validate?
if(ids.indexOf($elem.attr('id')) !== -1) {
// do some validation
var allowedChars = new RegExp("^[0-9\-]+$"),
str = String.fromCharCode(!event.charCode ? event.which : event.charCode);
// is it valid?
if (!allowedChars.test(str)) {
result = false;
}
}
return result;
}
function processPrimarySearch() {
// ...
}

Related

Allow only regex pattern in javascript

I want the user to input a number with format:
##/####
Where the "#" are numbers.
Here is the sample code:
(function() {
var previousValue = document.getElementById('myInput').value;
var pattern = /^\d{2}(\/\d{4})?$/;
function validateInput(event) {
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
<input id="myInput" type="text" maxlength=7 value="" />
I can only write the first two numbers, but I can't type anything else after that, even though the regular expression seems correct to me.
---EDIT---
After all the answers, I want to point out that I already have a validator that fires on the submit, which tells the user if they have typed in the correct form; I just wanted to somehow "guide" the user in the typing of the input.
Use this var pattern = /^\d{0,2}(\/\d{0,4})?$/; when user is typing which basically allow to type the pattern you want. And when input become blur check length of input field and validate accordingly.(or you can use minlength(make it equal to maxlength) if you are using input field in form then you will not require blur method)
(function() {
var previousValue = document.getElementById('myInput').value;
var pattern = /^\d{0,2}(\/\d{0,4})?$/;
function validateInput(event) {
len = event.target.value.length;
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
(function() {
function validateInput(event) {
len = event.target.value.length;
(len===7) ? console.log("Success") : console.log("fail");
}
document.getElementById('myInput').onblur = validateInput;
}());
<input id="myInput" type="text" milength=7 maxlength=7 value="" />
<button>1</button>
Probably you want to allow regex to validate correct when the user is still not finished with writing it down.
var pattern = /^\d{0,2}(\/\d{0,4})?$/;
But you would still need to validate it after that, so onblur check might be better.
First of all, you can analyze your regex here.
You will find that your regex:
/^\d{2}\/\d{4}?$/
matches a string that begins with two digits, followed by a slash and then 4 digits repeated zero or one time (the question mark).
Just remove the question mark in order to match the exact pattern.
From my point of view your problem is in event that you handle. Onkeyup fired after any key up. And if the current value of input field is not matched with your pattern you replace it with old one value. I think you need to handle change event instead of keyup: codepen
To me, your approach of validating seems wrong! You have to wait to do the validation until the user blurs away from the input field.
What I am suggesting is to use the event onblur instead of onkeyup, to perform your validation. How can you validate an input which is not completed?
Or else, you could program the event onkeypress, to check the key which is struck is one you need. You will have to deal with key codes and all.
EDIT
Managed to tackle the problem! Check if the following helps.
(function() {
var previousValue = document.getElementById('myInput').value;
function validateInput(event) {
event = event || window.event;
var newValue = event.target.value || '';
var previousValueLength = document.getElementById('myInput').value.length;
var pattern = /^\d{2}\/\d{4}$/;
switch(previousValueLength){
case 0:
pattern = /^$/;
break;
case 1:
pattern = /^\d{1}$/;
break;
case 2:
pattern = /^\d{2}$/;
break;
case 3:
pattern = /^\d{2}\/$/;
break;
case 4:
pattern = /^\d{2}\/\d{1}$/;
break;
case 5:
pattern = /^\d{2}\/\d{2}$/;
break;
case 6:
pattern = /^\d{2}\/\d{3}$/;
break;
}
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
https://jsfiddle.net/zjg6azjn/9/

RegEx validation Error javascript for Numeric Value

I am trying to validate Integer and float value in javascript but failed to achieve it. It always allow "." . Please help me to solve this regex error.
result :- 1,1.1,.1
I am checking in onkeypress event. It is not working in that.
<input type="text" onkeypress="Test()" style="width:100px"/>
function Test() {
var code;
var character;
if (document.all)
{
code = window.event.keyCode;
}
else {
code = arguments.callee.caller.arguments[0].which;
}
var character = String.fromCharCode(code);
var txt = new RegExp('([0-9]*[.])?[0-9]+');//only numueric value
if (!txt.test(character)) {
if (document.all) {
window.event.returnValue = false;
}
else {
arguments.callee.caller.arguments[0].preventDefault();
}
}
}
You need to do 2 things:
1) Use "onkeyup" instead of "onkeypress"
2) Use this RegExp:
(^(- )?[0-9]*([\.]?[0-9]+)?$)
I placed it in an online tester and you can test it here:
https://regex101.com/r/zL1mB0/3
Updated Answer Version since your first Question Edit

Having difficulty validating textarea input

I have a form with the target="_blank", and onsubmit="return validateForm()", as well as a textarea named "wordList". Here is my validateForm() function
function validateForm() {
var x = document.forms["form1"]["wordList"].value;
if (x == null || x == "") {
alert("Word list cannot be empty.");
return false;
}
}
This works fine to test for an empty input, however I need to also verify that the wordList has a minimum number of lines of text. I have tried inserting a php block after this if statement, but by calling 'explode()', it ends up opening a new tab regardless of if there is input or not. Here's what I mean:
function validateForm() {
var x = document.forms["form1"]["wordList"].value;
if (x == null || x == "") {
alert("Word list cannot be empty.");
return false;
}
<?php
$wordInput = explode("\n", str_replace("\r", "", $_POST['wordList']));
?>
}
I'm not sure how to reference the wordList in the php block when it's on the same page, but either way, whenever I click a submit button, even with an empty textarea, it opens the current page in another tab.
Is there a better way than using php to count and validate the number of lines in the text area?
It is because php code executes at server side not client side, so you need to write javascript alternative code instead of php code ...
Here regardless of what you write in php code it won't return true or false and you want get wordList ... so it will submit the form from the client side
var text = $("#wordList").val();
var lines = text.split(/\r|\r\n|\n/);
var count = lines.length;
console.log(count); // Outputs 4
Use it in you if condition to check countLines more than 2
var text = $("#wordList").val();
var lines = text.split(/\r|\r\n|\n/);
var count = lines.length;
console.log(count); // Outputs 4
var countLines = document.getElementById("wordList").rows;
Codepen URL for reference - http://codepen.io/nagasai/pen/gMrpre
You have to use JavaScript for this purpose. You need to find out how many linebreaks the textarea have. Here a reference to a similiar question.
enteredText = textareaVariableName.val();
numberOfLineBreaks = (enteredText.match(/\n/g)||[]).length;
Then you have to prevent the action caused by pressing the submit button with JS if the number of linebreaks doesnt match your criteria.
Here a question for handling this.

Internal Site Search Jquery against a RegExp

Where am I going wrong? Even one error would help please.
I have an HTML input and a submit button. The idea is to:
Submit search string
Get string value.
Compare string value to regex.
If legit, find instances of the string in the DOM.
Then scroll to the first instance of the matched string as it sits in the DOM.
$("#submit").on("click", function () {
//regex to be compared against
var search = new RegExp();
search = /(^\w[A-z]+)$|(^\d[0-9\.x\.X\.m\.M]+)/;
//grab the string value from the search input
var userin = $("#searchin").val();
var compare = userin.test(search);
if (compare === true) {
var treebody = $('html, body').contents().filter(function (userin) {
if ($('html, body').contents() === userin) {
$('html, body').animate({'scrollTop' : $(treebody).position().top}, 700)
} else {
alert("Please search again or scroll down to find your desired content");
}
});
} else {
alert("Sorry, we couldn't match your search. Please try a region or place or a billboard size e.g. 9x13 ");
}
});
Change the line
var compare = userin.test(search);
it should be
var compare = search.test(userin);
Also check you regular expression. Here is a good reference RegEx.

testing user entry on keyup and regex

In my case the requirement is like -
The first name should allow alphabets, some chars like comma, dash and ascent chars.
The code works fine when we try to paste the ascent chars or use "abctajpu" add on in firefox. But as soon as user types in ALT+0192 or any ALT key with num pad.
The keyup function does not work. It lets the user to key in every possible combination with the ALT key.
Here is the sample code..
var namePattern = /^[a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]$/g;
var negateNamePattern = /[^a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]/g;
$("#First_Name").bind('keyup paste altKey', function(event) {
var obj = $(this);
if (event.type == 'paste') {
setTimeout(function() {
validateRealTime(event, obj, namePattern, negateNamePattern)
}, 1);
} else {
validateRealTime(event, obj, namePattern, negateNamePattern);
}
});
The key up event will still be fired when they do any ALT key with num pad, however only when they stop typing will the new character be appended.
Is there a specific reason why you need to do a key up event?
You could validate your field whenever they lose focus on the input.
Also, can we see your validateRealTime function?
EDIT
I think I've figured out a way to accomplish what you want.
We'll have to change your function to validate a string passed instead of getting the value of the object:
function validateRealTime(str, regExPattern, negateRegExPattern) {
var fieldVal = str;
fieldVal = fieldVal.replace(/^(\s+)/g,'');
fieldVal = validateInput(fieldVal, regExPattern, negateRegExPattern);
// return the new and validated value
return fieldVal;
}
I've removed the event from the function, but you can add it if you are using it somewhere else.
Also, we need to change from a keyup to a keypress event. This will allow us to determine when the ALT is pressed (ALT + # = one keypress, whereas ALT + # = # keyups)
Futhermore, since the value of the input gets updated on keyup, we need to make sure that on keyup only the validated string appears.
var validatedValue; // Store validate value to display on 'keyup'
var namePattern = /^[a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]$/g;
var negateNamePattern = /[^a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]/g;
$("#First_Name").bind('keyup', function(event){
$(this).val(validatedValue);
})
.bind('keypress paste', function(event){
var obj = $(this);
var char;
var string;
var newval;
if (event.type == 'paste'){
setTimeout(function(){validateRealTime(obj.val(), namePattern, negateNamePattern)}, 1);
} else {
// Get the ASCII code of the key pressed and get the Char representation of it
// When we do an ALT+#, it returns only one ASCII value
char = String.fromCharCode(event.keyCode);
// Get the current string and append the character added by the ALT
// We need to do this, because the val() is not updated yet, it still contains
// the old value
string = obj.val() + char;
validatedValue= validateRealTime(string, namePattern, negateNamePattern);
}
});
Also, I have not tested the paste event.
Finally its working....here is the working code...
$("#First_Name").bind('keyup paste', function(event){
var obj = $(this);
if(event.altKey) {
$("#First_Name").bind('keypress', function(event){
setTimeout(function(){validateRealTime(event, obj, namePattern, negateNamePattern)}, 1);
});
} else if (event.type == 'paste'){
setTimeout(function(){validateRealTime(event, obj, namePattern, negateNamePattern)}, 1);
} else {
validateRealTime(event, obj, namePattern, negateNamePattern);
}
});
Thanks a lot for the guidance...the trick was to delay the time so that keyup gets the typed in character.

Categories