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.
Related
I have a textarea and a dropdown set. I have it set so if a user does #name (or anything) it will display a dropdown list of users with specified input. I don't know how to do the regex for searching an array for an #name within it.
Example: User types "Hi #bob", then array is ["Hi","#bob"];
How do I find where #bob is and if a user hit spaces afterwords, the regex detects if a space is placed right after it.
example code I have tried
$(document).keypress(function(event){
var keycode = (event.keyCode ? event.keyCode : event.which);
if(keycode == 64) { //Enter keycode
$('.postingArea').on("keyup", function(){
var inputVal = $(this).val();
var res = inputVal.split(" ");
console.log(jQuery.inArray( "#/w/", res ));
var myString = inputVal.match(/#([^ ]*)/)[1];
var resultDropdown = $(this).siblings(".result2");
if (jQuery.inArray( "#", res ) < 1) {
resultDropdown.empty();
}else {
$.get("../Admin/Users/SearchUser.php", {userAtd: myString}).done(function(data){
// Display the returned data in browser
resultDropdown.html(data);
});
}
})
}
This sort of works, but jQuery.inArray doesn't accept regex, so it only works when # is clicked, but not for the rest of the letters following. And then it should detect when there is a space after the word so then it knows that the # is done.
When doing console.log(res); The output in log is ["this", "is", "a", "test", "#user"]
What I need is for it to detect when # is clicked and then when that part of the array is finished such as hitting space since hitting space makes the array res now
["this", "is", "a", "test", "#user",""]
You could use the following regex to extract every words that start by "#" and that have space after it in a string.
/#[a-z\d]+/ig
See examples : https://regex101.com/r/WDZNyl/1
Once you get the list, it will be easier for you to find the desired values in database.
I figured out the answer, #Flo's response helped a bit coming up with this. I had to detect two different array lengths and compare the two and find where the # started between both arrays and then set a variable x to the length of the original input and then do a .test as my if statement. Code down below
// #'d feature
$(document).keypress(function(event){
var keycode = (event.keyCode ? event.keyCode : event.which);
if(keycode == 64) { //Enter keycode
$('.postingArea').on("keyup", function(){
var inputVal = $('.postingArea').val();
var res = inputVal.split(" ");
var res2 = inputVal.match(/#[a-z\d]+/ig);
var resultDropdown = $(this).siblings(".result2");
var x=0;
if(x <= res2.length){
x = res.length-1;
}
if(/#[a-z\d]+/ig.test(res[x])) {
var myString = res[x];
$.get("../Admin/Users/SearchUser.php", {userAtd: myString}).done(function(data){
// Display the returned data in browser
resultDropdown.html(data);
});
}else {
resultDropdown.empty();
}
})
}
})
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/
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() {
// ...
}
function stripspaces(input)
{
input.value = input.value.replace(/\s+/gi," ");
}
I written this function. It is working but when I point the mouse pointer or moving with left arrow in between word and giving space it is jumping to the last. Can anyone give me the solution?
You can prevent the input by calling e.preventingDefault we can simply test if the space key has been pressed and if there's a space either side of the cursor then prevent entry.
document.addEventListener('DOMContentLoaded', function() {
var input = document.getElementById('myInput');
input.addEventListener('keydown', function(e){
var input = e.target;
var val = input.value;
var end = input.selectionEnd;
if(e.keyCode == 32 && (val[end - 1] == " " || val[end] == " ")) {
e.preventDefault();
return false;
}
});
});
<input type="text" id="myInput">
This still has the issue that it won't prevent pastes into the box with double spaces. So it may be worth still replacing multiple spaces on focus loss to be sure that the input never contains multiple contiguous spaces.
I just came across the same use case. If you also want to handle copy/paste or any other way the input's value could change, use the input event:
document.addEventListener('DOMContentLoaded', function() {
// get a reference to the input element
const input = document.querySelector('#myInput');
// guard clause to check if `#myInput' actually exists in the current DOM
if(!input) return
// Run this every time the input's value changes
input.addEventListener('input', e => {
// get the value
const value = e.target.value
// check if the value isn't exactly ' ' and ends with a space
const hasTrailingSpace = value !== ' ' && value.charAt(value.length-1) === ' '
// extract words, remove empty words (handles double spaces)
const words = value.split(' ').filter(el => el !== '')
// create the sanitized value
let sanitizedValue = words.join(' ')
// add a trailing space if there was one
if( hasTrailingSpace ) sanitizedValue += ' '
// apply the sanitized value to the input's value
e.target.value = sanitizedValue
})
})
<p>Try inserting double spaces now! Also try copy/paste from somewhere else</p>
<input type="text" id="myInput">
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.