I am new to Javascript.
I need to make an username input, then validate it.
The username entered must not be one of the elements in this array: ["admin", "administrator", "demo", "user"] etc. The array can be longer.
I made this so far, but it works only for the 1st element in the array.
function arrayValidation () {
nonoUser = ["username", "admin", "administrator", "demo"];
valueOfInput = document.getElementById("user").value; // "user" here is id of input
for (var i = 0; i < nonoUser.length; i++) {
if (valueOfInput == nonoUser[i]) {
alert("you cant use this username");
}else {
return;
}
}
}
Try this:
function arrayValidation () {
nonoUser = ["username", "admin", "administrator", "demo"];
valueOfInput = document.getElementById("user").value; // "user" here is id of input
var isValid = true;
for (var i = 0; i < nonoUser.length && isValid; i++) {
if (valueOfInput == nonoUser[i]) {
isValid = false;
}
}
if (isValid) {
// Username is valid
}else{
// Username is invalid
}
}
However, you should never trust data that's sent to the server (Validate server-side as well)
It's trivial to change the js as a user.
This should point you in the right direction:
document.getElementById("user").onkeyup = function(){
var nonoUser = ["username", "admin", "administrator", "demo"];
nonoUser.indexOf(this.value) === -1 ? false : this.value = '';
}
demo: http://jsfiddle.net/Le2xC/
I also hope you're validating this server-side as well, otherwise users will still be able to use your "nono" usernames.
you need to add return false; to the code section with the alert, not the else statement.
The comments here should help you to see why your code isn't working as you expect:
// Your original code:
function arrayValidation () {
nonoUser = ["username", "admin", "administrator", "demo"];
valueOfInput = document.getElementById("user").value; // "user" here is id of input
for (var i = 0; i < nonoUser.length; i++) {
if (valueOfInput == nonoUser[i]) {
alert("you cant use this username");
} else {
// Using return here is the problem.
// This else block will run if a valid username was entered.
// The return statement stops execution of the function, thus ending the loop.
// So if the loop passes the test the first time, this return
// statement will stop the loop and function from completing
// the checks against the other keywords.
return;
}
}
}
This is your code modified to work as you expect:
function arrayValidation () {
nonoUser = ["username", "admin", "administrator", "demo"];
valueOfInput = document.getElementById("user").value; // "user" here is id of input
for (var i = 0; i < nonoUser.length; i++) {
if (valueOfInput == nonoUser[i]) {
alert("you cant use this username");
// We can end the function check return here.
// There's no point checking the others, as we've found an invalid one.
return false; // Return a meaningful result
}
// No need for an else statement either.
}
}
As many have pointed out, client side validation should be considered an optional extra, and server-side validation as essential.
Related
I have looked through the many answers to the "closure" issue but cannot get any to work on my specific issue.
The following js code takes a json file and stores it and then does some form validation based on the data.
The problem is on submission of the form and execution of the validate function I should see two errors but I only get the error for the last field (logged in the console).
This is an obvious closure problem but having spent all day on it I still can't fix it. Below is the code, the click event is at the bottom...
I am only checking the min length rule at this moment.
// Get the json file and store
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'js/rules.json');
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
callback(xobj.responseText);
}
};
xobj.send(null);
}
// Load json...
loadJSON(response);
// Create global vars...
var lookup = [], errors = [], i, e, id, lookupId, minLength;
function response(responseData) {
// Create objects from json data
var rulesSet = JSON.parse(responseData);
// Loop through objects
for (i = 0; i < rulesSet.length; i++) {
// Create a lookup for each object that can be used later
lookup[rulesSet[i].id] = rulesSet[i];
}
// Loop through form elements and store id's
// Validate the form
function validate(e) {
var elements = document.getElementsByTagName('input');
for (e = 0; e < elements.length; e++) {
id = elements[e].getAttribute('id');
lookupId = lookup[id].rules; var rules;
// Loop through rules of the matched ID's
for (rules of lookupId){
// Check if there is a min length rule
if(rules.name === 'min_length') {
minLength = rules.value.toString();
// Check if the rule is valid (is a number)
if(isNaN(minLength) || minLength.length === 0){
// Log an error somewhere here
// Run the minLength function and report an error if it fails validation
} else if(!checkMinLength(minLength, id)) {
errors[errors.length] = id + " - You must enter more than " + minLength + " characters";
}
}
}
// If there are errors, report them
if (errors.length > 0) {
reportErrors(errors);
//e.preventDefault();
}
}
}
validate();
// Check the length of the field
function checkMinLength(minLength, id){
var val = document.getElementById(id).value;
if(val < minLength){
return false;
}
return true;
}
// Error reporting
function reportErrors(errors){
for (var i=0; i<errors.length; i++) {
var msg = errors[i];
}
console.log(msg);
}
$('#email-submit').on('click',function(e){
validate(e);
});
}
Possibly not relevant but below is the json that is loaded...
[
{
"id": "search",
"rules": [
{
"name": "min_length",
"value": "5"
},
{
"name": "email"
}
]
},
{
"id": "phone-number",
"rules": [
{
"name": "min_length",
"value": 8
}
]
},
{
"id": "surname",
"rules": [
{
"name": "min_length",
"value": 10
}
]
}
]
And the basic form to validate...
<form action="index.html" name="searchForm" id="search-form">
<label for="search">Email</label>
<input type="text" id="search" name="email" placeholder="Enter email">
<input type="text" id="phone-number" name="name" placeholder="Enter name">
<button type="submit" id="email-submit">Submit</button>
</form>
The code does exactly what you tell it to do
// Error reporting
function reportErrors(errors){
for (var i=0; i<errors.length; i++) {
var msg = errors[i]; <-- setting the variable on each iteration
}
console.log(msg); <-- reads the last value from the last iteration
}
You need to move the console inside of the for loop
// Error reporting
function reportErrors(errors){
for (var i=0; i<errors.length; i++) {
var msg = errors[i];
console.log(msg);
}
}
or do not even loop
// Error reporting
function reportErrors(errors){
console.log(errors.join("\n"));
}
And now a logic issue, you are declaring a function inside a for loop
function response(responseData) {
// ignored code //
var elements = document.getElementsByTagName('input');
for (e = 0; e < elements.length; e++) {
function validate(e) { <-- THIS SHOULD NOT BE IN THE FOR LOOP
Again just like the error message thing, only the last one is going to be there...
Create more readable scheme without closure.
var submitButton = document.querySelector('#email-submit')
function validate (evt) {
async function loadRules (url) {
var rawData = await fetch(url)
return await rawData.json()
}
function reportErrors (error) {
evt.preventDefault()
// Report logic here
}
function evaluate (rules) {
// Your validate rules here
// loaded rules in rules object
// eg. rules[0]['rules'].name
}
loadRules('js/rules.json').then(evaluate)
}
submitButton.addEventLister('click', validate)
I have a user profile form with 15 text fields and some dropdown and an textarea. the scene is that user can input field in profile form. On save it is no necessary to fill all fields, whatever the user fills in fields i have to validate and save in database via ajax call.
for now i am using validation like this,
var first_name = document.getElementById('id_candidate_profile-first_name').value;
....
var status = false;
if(first_name != ''){
status = regex_test(first_name, ck_name);
if(status==false){
document.getElementById('candidate_profile_error-first_name').innerHTML = "first name should only have alphabets";
}
else{
status = true;
}
}
if(middle_name != "" & status = true){
status = regex_test(middle_name, ck_name);
if(status==false){
document.getElementById('candidate_profile_error-middle_name').innerHTML = "middle name should only have alphabets";
}
else{
status = true;
}
}
if (last_name != '' & status = true){
status = regex_test(last_name, ck_name);
if(status==false){
document.getElementById('candidate_profile_error-last_name').innerHTML ="last name should only have alphabets";
}
else{
status = true;
}
}
if (date_of_birth != '' & status = true){
status = regex_test(date_of_birth, ck_date);
if(status==false){
document.getElementById('candidate_profile_error-date_of_birth').innerHTML ="date of birth should be in YYYY-MM-DD format";
}
else{
status = true;
}
}
if (birth_place != '' & status = true){
status = regex_test(birth_place, ck_name);
if(status==false){
document.getElementById('candidate_profile_error-birth_place').innerHTML ="birth_place should only have alphabets";
}
else{
status = true;
}
}
if (nic != '' & status = true){
status = regex_test(nic, ck_name);
if(status==false){
document.getElementById('candidate_profile_error-nic').innerHTML ="nic should be in this format 12345-1234567-1";
}
else{
status = true;
}
}
if (status = true) {
// made ajax call
}
function regex_test(variable, regex){
var _result = false;
if(!regex.test(variable)){
_result = false;
}
else {
_result = true;
}
return _result;
}
Can be seen that there are lots of nested if else involved that irritate me, need some better way to do this? any best alternative?
You could create an array of validation objects, each object containing properties reg_ex, field, error_msg_container_id and error_msg:
var validationRules = [
{ reg_ex: first_name,
field: ck_name,
error_msg_container_id: candidate_profile_error-first_name,
error_msg: "first name should only have alphabets" },
{ reg_ex: date_of_birth,
field: ck_date,
error_msg_container_id: candidate_profile_error-date_of_birth,
error_msg: "date of birth should be in YYYY-MM-DD format" }
];
In the validation function, you just iterate through the whole array. That also makes it easier to maintain further input fields which you might add later.
P.S.: If you don't know how to iterate over an array, let me know.
Edit: Since requested by OP, an iteration function would look similar to this:
function isFormDataValid() {
for (i=0; i< validationRules.length; i++) {
// do the validation inside here, it will be repeated once for each validation rule;
}
return status;
}
In case you need variable property names from the array to read/write, use this syntax
Object[variable]
where variable contains the string that is the name of the property you need to access.
var myObject = {
name: "peter",
age: 46
};
var validationRules = [ { fieldname: 'name'}, { fieldname: 'age' } ];
for (var i=0; i< validationRules.length; i++) {
alert(myObject[validationRules[i].fieldname]);
}
You can use any form validation library. I personally recommend Parsley.
There's a simple validation form example: http://parsleyjs.org/doc/examples/simple.html
i have an array which contains some values. i want if the textbox's value contains a value from any of the element of that array it will show alert "exists", otherwise "doesn't exists"
I have tried the following code:
$('[id$=txt_Email]').live('blur', function (e) {
var email = $('[id$=txt_Email]').val();
var array = ['gmail.com', 'yahoo.com'];
if (array.indexOf(email) < 0) { // doesn't exist
// do something
alert('doesnot exists');
}
else { // does exist
// do something else
alert('exists');
}
});
But this is comparing the whole value with the array's element. i want to use contains function as we can in C# with string.Please help me.
I want if user type "test#gmail.com" it will show exists in array. if user enter "test#test.com" it will alert doesnot exists.
I think you want
$.each(array, function () {
found = this.indexOf(email);
});
To find the match not exact string you need to do some thing like
Live Demo
arr = ['gmail.com', 'yahoo.com'];
alert(FindMatch(arr, 'gmail.co'));
function FindMatch(array, strToFind)
{
for(i=0; i < array.length; i++)
{
if(array[i].indexOf( strToFind) != -1)
return true;
}
return false;
}
$(document).on('blur', '[id$=txt_Email]', function (e) {
var email = this.value, array = ['gmail.com', 'yahoo.com'];
if (email.indexOf('#')!=-1) {
if ($.inArray(email.split('#')[1], array)!=-1) {
alert('exists');
}else{
alert('does not exists');
}
}
});
FIDDLE
b is the value, a is the array
It returns true or false
function(a,b){return!!~a.indexOf(b)}
My knowledge of jQuery and more specifically javascript has always been very limited and I am working hard to get better.
With that in mind I am trying to create some sort of "extensible validation framework" in that I can create an object with a validation function and its error message, push it into an array and then call all those methods and report the messages from the ones that fail.
So first I did something very simple just to see that the basic validation worked which was this:
var selectedTourDate = $("#tourDate").val();
var list = $("#bookedTourDate *");
var isDateBooked = list.filter(function () {
return (this.innerHTML == selectedTourDate) ;
}).length !== 0;
if (isDateBooked) {
alert("Date invalid");
return;
}
This works fine.
Then I created my "framework" which is this:
function Validator(fn, errorMessage) {
this.validationFunction = fn;
this.errorMessage = errorMessage;
};
var validationRunner = {
validators: [],
errorMessages: [],
validationResult: true,
addValidation: function (validator) {
validationRunner.validators.push(validator);
},
validate: function () {
for (var validator = 0; validator < validationRunner.validators.length; validator++) {
if (validationRunner.validators[validator] instanceof Validator) {
var result = validationRunner.validators[validator].validationFunction();
validationResult = validationRunner.validationResult && result;
if (!result)
validationRunner.errorMessages.push(validationRunner.validators[validator].errorMessage);
}
}
},
getErrorMessage: function () {
var message = "<ul>";
for (var errorMessage = 0; errorMessage > validationRunner.errorMessages.length; errorMessage++) {
message += "<li>" + errorMessage + "</li>";
}
message += "</ul>";
return message;
}
}
And then modified the first block of code as follows:
var selectedTourDate = $("#tourDate").val();
var list = $("#bookedTourDate *");
var tmp = new Validator(function () {
return list.filter(function () {
return (this.innerHTML == selectedTourDate);
}).length !== 0;
}, "Date already booked");
validationRunner.addValidation(tmp);
validationRunner.validate();
var msg = validationRunner.getErrorMessage();
This does not work at all.
It seems that the problem is that in this statement:
return (this.innerHTML == selectedTourDate);
The "this" is the Validator object instead of the html element from the list which confuses me since as its inside the function of the "filter" method it should be.
Is there a way to correct this so I can accomplish what I am trying to do here?
this does have the correct value but there are some mistakes in the getErrorMessage function.
To check the value of this don't rely on a debugger's "watch variable" function but do a console.log which will give you the value at a specific point of the code execution.
My changes:
for (var errorMessage = 0; errorMessage < validationRunner.errorMessages.length; errorMessage++) {
message += "<li>" + validationRunner.errorMessages[errorMessage] + "</li>";
}
The errorMessage variable is only a index and not the actual error message. Also you used a "bigger than" instead of a "smaller than" sign.
Here's a fiddle
That is very odd, as this should be the current DOM element per jquery api.
The function should take an index as a parameter, though. So what about trying
return list.filter(function (i) {
return (list.get(i).innerHTML == selectedTourDate);
}).length !== 0;
I can’t figure out what is missing so that when e-mail is valid it will skip the last invalid message and move to next item on form for validation:
enter code here
if (document.form1.email.value.length > 0) {
var tst = document.form1.email.value;
var okd = ['bankofamerica.com','baml.com','magner.com','ml.com','ust.com','ustrust.com']
for (var i = 0; i < okd.length; i++) { okd[i] == okd[i].toLowerCase() }
var emailRE = /^[a-zA-Z0-9._+-]+#([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})$/
var aLst = emailRE.exec(tst)
if (!aLst) {
alert(tst + ' is not a valid e-mail')
} else {
var sLst = aLst[1].toLowerCase()
for (var i = 0; i < okd.length; i++) {
if (sLst == okd[i]) {
// alert(aLst[1] + ' is allowed');-->
}
}
if (i == okd.length) alert(aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.')
document.form1.email.select();
return false;
}
}
I'd recommend placing this code into a function, maybe named ValidateEmail().
In your loop: if you've determined the email is valid, return true;. This will prevent further execution. If that domain doesn't match, have it continue looping to check the others.
If the loop completes without returning true, you'll know it didn't match anything so return false; at the very end.
EDIT: Use try/catch instead:
if (document.form1.email.value.length > 0) {
var tst = document.form1.email.value;
var okd = ['bankofamerica.com','baml.com','magner.com','ml.com','ust.com','ustrust.com']
for (var i = 0; i < okd.length; i++) { okd[i] == okd[i].toLowerCase() }
try {
var emailRE = /^[a-zA-Z0-9._+-]+#([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})$/
var aLst = emailRE.exec(tst)
if (!aLst)
throw (tst + ' is not a valid e-mail');
// isValidDomain will be changed to 'true' only if it matches an item in the array
var isValidDomain = false;
var sLst = aLst[1].toLowerCase()
for (var i = 0; i < okd.length; i++) {
if (sLst == okd[i]) {
isValidDomain = true;
// We break here because a match has been found - no need to compare against the other domain names.
break;
}
}
if(!isValidDomain)
throw (aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.');
// If execution reaches here, you know it passed both tests!
return true;
}
catch(err) {
// This code block runs whenever an error occurs
alert(err);
document.form1.email.select();
return false;
}
}
throw basically acts like a goto command. It will jump directly to the catch(err) portion of the code.
More info about try, catch, and throw:
http://www.w3schools.com/js/js_try_catch.asp
http://www.w3schools.com/js/js_throw.asp
Thank you very much Colin!
I had to remove the following 2 lines to avoid halting the code from running on to next validation field:
isValidDomain = true;
// We break here because a match has been found - no need to compare against the other domain names.
// break - exits code from running on down to next item on page
}
}
if (!isValidDomain)
throw (aLst[1] + ' is not allowed. Please enter an email address with an authorized domain.');
// If execution reaches here, you know it passed both tests!
// return true; - was not needed, stops code from running on page
}
catch (err) {