I build form validation with the code below. It`s work but If some of required field is filled var msg contains undefinied value.
For example if username is filled but password not var msg contains
'undefinied'
Field is requred
How to avoid that ?
Here is the code:
var i = 0;
var error_msg = [];
var msg = ;
var errors = {
'username' : 'Field is required',
'password' : 'Field is requred',
'city' : 'City is required'
etc...... etc...
};
for(var x in errors) {
i++;
if(!$('#'+x).val()) {
error_msg[i] = errors[x];
}
}
if(error_msg.length > 0) {
for(var x = 0; x < errors_msg.length; x++) {
msg += errors_msg[x] +"\n";
}
}
One thing I see is:
var msg = ;
Should(could) be
var msg = "";
Did you also try to:
alert($('#'+x).length);
To see if jQuery finds the element? (if it returns 0, then its not found)
OK, besides the obviously broken for in loop and the missing assignment of msg.
This is your actual problem:
var error_msg = []; // new empty array
for(var x in errors) {
i++; // i starts with 1 this way!
// other code
}
So you're never setting the 0th index. Yes arrays start with index 0. So if you set an index that's bigger then the current length of the array, JavaScript will insert the missing elements before that index.
In your case, JavaScript will insert the default undefined at index 0 since the first index you set is 1.
Fixing
var error_msg = [];
for(var x in errors) {
if (errors.hasOwnProperty(x)) { // see note below
if(!$('#'+x).val()) {
error_msg.push(errors[x]); // append to the array
}
}
}
var msg = error_msg.join('\n'); // no need for an if, will be empty if there are no errors.
Note: See hasOwnProperty
This is not your problem, and so this is not really an answer, but comments don't support code very well:
if(error_msg.length > 0) {
for(var x = 0; x < errors_msg.length; x++) {
msg += errors_msg[x] +"\n";
}
}
For future reference, you never need to write that code:
msg = errors_msg.join('\n');
does the same thing.
Related
I'm trying to make a simple 'bad words' filter with javascript. It's meant to listen to any submit events on the page, then iterate through all input fields of the text type, check them for bad stuff by comparing the entered text with the word list, and finally return an according console.log/alert (for now).
I have two files: word-list.js with the critical words (loads first) and filter.js which pulls an array with all words from word-list.js.
My problems is, swear_words_arr[1] is 'undefined' and I don't understand why. I've been looking around for solutions, but still I can't seem to determine the reason for this. Help is much appreciated.
// get all inputs type = text and turn html collection into array
var getInputs = document.querySelectorAll("input[type=text]")
var inputs = Array.from(getInputs);
//var swear_alert_arr -> from in word-list.js
var swear_alert_arr = new Array();
var swear_alert_count = 0;
function reset_alert_count() {
swear_alert_count = 0;
}
function validate_text() {
reset_alert_count();
inputs.forEach(function(input) {
var compare_text = input.value;
console.log(compare_text);
for (var i = 0; i < swear_words_arr.length; i++) {
for (var j = 0; j < compare_text.length; i++) {
if (
swear_words_arr[i] ==
compare_text.substring(j, j + swear_words_arr[i].length).toLowerCase()
) {
swear_alert_arr[swear_alert_count] =
compare_text.substring(
j,
j + swear_words_arr[i].length
);
swear_alert_count++;
}
}
}
var alert_text = "";
for (var k = 1; k <= swear_alert_count; k++) {
alert_text += "\n" + "(" + k + ") " + swear_alert_arr[k - 1];
if (swear_alert_count > 0) {
alert("No!");
console.log('omg no bad stuff! D:');
} else {
console.log('no bad stuff found :)');
}
}
});
}
window.onload = reset_alert_count;
window.addEventListener('submit', function() {
validate_text();
});
It doesn't look like you've declared the array you're trying to access.
But, instead of loops with nested loops and keeping track of loop counters, just get a new array that contains any bad words in the submitted array. You can do this a number of ways, but the Array.prototype.filter() method works nicely:
let badWords = ["worse", "terrible", "horrible", "bad"];
let submittedWords = ["Good", "Terrible", "Great", "Fabulous", "Bad", "OK"];
// Loop over the submitted words and return an array of all the bad words found within it
let bad = submittedWords.filter(function(word){
// Do a case-insensitive match test. Return the word from the submitted words
// if it's on the bad word list.
return badWords.indexOf(word.toLowerCase()) > -1 ? word: null;
});
console.log("Bad words found in submitted data: " + bad.join(", "));
So, I have following js setup:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
Then,
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (NAMES[my_name] !== 185){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}
alert(JSON.stringify(NAMES , null, 4));
Here is a screenshot of the alert:
I hardcoded the number "185" for this example. I need to check if the id of 185 exists, then skip to else. I am not sure how to check it. I tried typeof, undefinedetc. but no luck.
(In other words, I should only have one "185").
Any help? Thanks!
If I understood correctly what you are trying to achieve, you have to iterate over NAMES and check every element. For example, you could do it using [].some javascript function:
if (!NAMES.some(function(v){return v[my_name]})) {
...
} else {
}
If you want to remove duplication you can just use NAMES as an object instead of array like this
var all_names = [185, 185, 181],
NAMES = {};
for (var j = 0; j < all_names.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
NAMES[my_name] = ["sean","sdfsd","sdfsfd"];
}
alert(JSON.stringify(NAMES, null, 4));
First of all I would recommend making a JS Fiddle or CodePen out of this so people can see the code running.
I believe that the issue is that NAMES[my_name] is not doing what you think it is. NAMES is an Array so when you say NAMES[my_name] you are really asking for the ITEM in the array so you are getting the entire object that you create in the INFO function. What you really want is to see if the object has an attribute that matches the value (e.g. "185" from the my_names array).
This is not the prettiest code but it will show you how to do what you really want to do:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
all_names = ["185", "186", "185"]
for (var j = 0; j < all_names.length; j++) {
var my_name = all_names[j];
if (NAMES.length == 0) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
} else {
var match = false;
for (var x = 0; x < NAMES.length; x++) {
console.log(NAMES[x][my_name] + ' : ' + my_name);
if(NAMES[x][my_name]) {
match = true;
}
}
if (!match) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}
}
}
alert(JSON.stringify(NAMES , null, 4));
Note the if that looks at NAMES[x][my_name] - this is asking if the item at array index 'x' has an attribute of 'my_name' (e.g. "185"). I believe this is really what you are trying to do. As its after midnight I assure you that there is more concise and pretty JS to do this but this should show you the basic issue you have to address.
Try this code using hasOwnProperty method :
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (!NAMES[my_name].hasOwnProperty("185")){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}
I'm working on exercism question and am stuck on one of the jasmine-node based tests, which says that I should be able to generate 10000 random names without any clashes (e.g. 2 randomly generated names match). This is the test:
it('there can be lots of robots with different names each', function() {
var i,
numRobots = 10000,
usedNames = {};
for (i = 0; i < numRobots; i++) {
var newRobot = new Robot();
usedNames[newRobot.name] = true;
}
expect(Object.keys(usedNames).length).toEqual(numRobots);
});
What I think I need to do is:
Create an array to hold all the names (robotNames),
Each time a name is generated, check if it exists in the array,
If it does, generate another name,
If it doesn't, add it to the array.
And here is my code so far...
"use strict";
var robotNames = [];
var name;
var Robot = function() {
this.name = this.generateName();
};
Robot.prototype.generateName = function() {
var letters = "";
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var numbers = "";
var digits = "0123456789";
// generate random characters for robot name...
for( var i=0; i < 2; i++ ) {
letters += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
};
for( var i=0; i < 3; i++ ) {
numbers += digits.charAt(Math.floor(Math.random() * digits.length));
};
name = letters+numbers;
// Loop through array to check for duplicates
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
this.generateName();
return;
} else {
robotNames.push(name);
}
}
return name;
};
Robot.prototype.reset = function() {
this.name = this.generateName();
};
module.exports = Robot;
The test fails with an error message: "Expected 9924 to equal 10000."
The '9924' number is slightly different each time I run the test. I'm thinking this means the generateName function is eventually generating 2 matching random names. It seems as though my loop for checking duplicates is not being run and I'm not sure why.
I have tried a couple of different versions of the loop but with no success. So my questions is a) is my approach correct and there is something wrong with the syntax of my loop? or b) have I got the wrong idea about how to check for duplicates here?
Any pointers appreciated, thanks.
The problem is in this bit:
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
this.generateName();
return;
} else {
robotNames.push(name);
}
}
...you probably only want to push your name if NONE of the names fail to match. Here you're adding it to the list as soon as you find ONE that doesn't match. You want something more like:
for(var i = 0; i < robotNames.length; i++) {
if (name == robotNames[i]) {
return this.generateName();
}
}
robotNames.push(name);
(actually, combined with the fact that you weren't even returning the recursive call to this.generateName(), I'm not sure how your program could work...)
Find a library with an implementation for Sets. Collections.js is a good example.
One property of a set is that it doesn't have duplicates. So when you add a value to a set it will look for a duplicate and then add the value if no duplicate exists.
I need to check to 1 array value, if value duplicated, it will pop up alert.
Here is the function :
function checkDuplicateTenure(){
var f = document.frmPL0002;
var supplgrid = document.getElementById("mdrPymtGrid2");
var len = (supplgrid.rows.length) - 1;
for(var i=0;i<len;i++){
if (f.cbo_loanTenure[i+1].value == f.cbo_loanTenure[i].value) {
alert("DUPLICATE LOAN TENURE IN MONTH(S)");
}
}
return false;
}
That function is works if got duplicate value in array, but if all value is different, its will hit js error if (f.cbo_loanTenure[i+1].value == f.cbo_loanTenure[i].value) { Unable to get property 'value' of undefined or null reference.
Thanks
This is a simple out of bounds error. Fix it by using this:
for (var i=0;i<len-1;i++) {
So, i+1 will never be the same as len.
change it
for(var i=0;i<len-1;i++){
if (f.cbo_loanTenure[i+1].value == f.cbo_loanTenure[i].value) {
alert("DUPLICATE LOAN TENURE IN MONTH(S)");
}
}
suppose your loop runs 5 times and you can set i+1 inside the loop it comes 6 which is undefined index that why js error occurs
Try this:
function checkDuplicateTenure(){
var f = document.frmPL0002;
var supplgrid = document.getElementById("mdrPymtGrid2");
var len = (supplgrid.rows.length) - 1;
for(var i=0;i<len-1;i++){
if (f.cbo_loanTenure[i+1].value == f.cbo_loanTenure[i].value) {
alert("DUPLICATE LOAN TENURE IN MONTH(S)");
}
}
return false;
}
I have the following javascript object
[Object { url="http://domain.com/abc", qty="1" }, Object { url="http://myurl.com/cde", qty="2" }]
I want to be able to loop through the object and output the URL using console.log() based on the qty variable.
So in this instance domain.com/abc would display once & the myurl.com/cde would display twice as the qty is set to 2.
I have something like the following but needs some work..
cart.forEach(function(value) {
var qty = value.qty;
var url = value.url;
var i = 0;
while ( i < qty ) {
// logic needed here (i believe)
i++;
}
}
That's how one can implement String.repeat in JS:
var repeatedString = Array(repeatsCount + 1).join(stringToRepeat);
... so in your case it'll be just ...
console.log(Array(+value.qty + 1).join(value.url));
Unary plus is a shortcut for Number(value.qty): it looks like you got a string there.
But it looks you actually need to collect all the urls instead. That's one possible way to do that:
var arrayOfUrls = [];
cart.forEach(function(value) {
for (var i = value.qty; i--) {
arrayOfUrls.push(value.url);
}
});
Alternative (.reduce-based):
var arrayOfUrls = cart.reduce(function(arr, value) {
for (var i = value.qty; i--) {
arr.push(value.url);
}
return arr;
}, []);