How to show if date is invalid in javascript - javascript

This is what I tried so far but still nothing changed. I don't where to start to maybe someone professional can help me get through with this. This is for validation purposes.
Code:
$(function(){
var len = $('#groupContainer > div').length;
var arr = [];
for(var i=0; i < len; i++){
var number = $('#number_' + [i + 1]);
var date = $('#date_' + [i + 1]);
var count = i + 1;
var message ="";
console.log(number)
var a = number.map(function(){
return this.value;
});
var b = date.map(function(){
return this.value;
});
var newObj = {number: a[0], date: b[0]}
arr.push(newObj);
}
var messages={};
var message="";
for(var c = 0; c < arr.length; c++)
{
var groupMessage=false;
for(var d in arr[c])
{
if(arr[c].hasOwnProperty(d))
{
if(arr[c][d] == "")
{
if(messages[d]==undefined) {
messages[d]={groups:[]};
}
messages[d].groups.push(c+1);
}
}
}
}
var lastgroup=""
for(i in messages){
m = messages[i];
var date = $('#date_' + i);
console.log(date)
if(m.groups.join(",")==lastgroup) {
message = message.replace("Group "+m.groups.join(",")+" ","Group "+m.groups.join(",")+":\n");
if(m == "Date" && date.length != 8)
{ message += i + ' is invalid!\n';
}
message+=i+" is required!\n";
}else {
message+="Group "+m.groups.join(",")+" "+i+" is required!\n";
}
lastgroup = m.groups.join(",");
}
if(message)
{
alert(message);
}
});
Fiddle
If all field is not filled show:
Group 1, 2 Number is required!
Group 1, 2 Date is required!
Valid date must be mm/dd/yy
And if date is not really a date:
Group 1, 2 Date is invalid.
And if one of the inputs is invalid.
Group 2 Date is invalid.
If all field is filled do nothing.

I recommend categorize objects by class, example:
.txtNumber for Number
.txtDate for date
You can use regExpAllow for keypress event and regexpMatch for the submit validation.
KeyPress Validation
$(document).on('keyup','.txtDate', function() {
var regExpAllow = new RegExp('[^0-9/]', 'g');
$(this).val($(this).val().replace(regExpAllow,''));
});
$(document).on('keyup','.txtNumber', function() {
var regExpAllow = new RegExp('[^0-9.]', 'g');
$(this).val($(this).val().replace(regExpAllow,''));
});
Submit Validation
$(document).on('click','#btnSubmit', function() {
var regExpMatch = new RegExp('^[0-3][0-9]/[0-1][0-9]/[1-2][0-9]{3}$');
$('.txtDate').each(function() {
if ($(this).val().match(regExpMatch) != null) {
alert('Valid Date:'+$(this).val());
} else {
alert('Invalid Date:'+$(this).val());
}
});
regExpMatch = new RegExp('^[0-9].[0-9]{3}$');
$('.txtNumber').each(function() {
if ($(this).val().match(regExpMatch) != null) {
alert('Valid Number:'+$(this).val());
} else {
alert('Invalid Number:'+$(this).val());
}
});
});
JSFiddle example: http://jsfiddle.net/BernardoBJ/o5dbnt51/4/
With this you can validate that characters can be entered and how it will be your final result (You can also validate the same way the regular expression of numbers if you want).
Implements this logic in your code.
note: gets a value that properly validate dates and your numbers format.

All that mapping and looping is hard to follow...just loop through the elements once and deal with each type within the loop
function validate(){
var errors = false,
$cont = $('#groupContainer');
// remove prior errors
$cont.find('.error').remove();
// loop over inputs
$cont.find(':input').each(function () {
// use id to sort out type
var type = this.id.split('_')[0],
value = this.value,
msg = null;
if (!value) {
msg = 'This is required';
} else if (type === 'date') {
if (/**** your invalid date method ***/ ) {
msg = 'Invalid Date';
}
} else if (type === 'number') {
if (isNaN(+value)) {
msg = 'Not a number';
}
}
if (msg) {
errors = true;
$(this).after('<span class="error">' + msg + '</span>')
}
});
return !errors;
}
alert( validate() ? 'Form is valid' :'Oooops! Not valid');
It's up to you to do date validation as no format was given
DEMO

Related

replace the eval with something safer

I created a calendar with the flatpickr.js library. I want to enable only the dates that are present in the arreys dateCorfu, dateZante and datePag selected from a dropdown (with the attribute name="destinazione").
I'm not a coder but I wrote the below code using the eval method, this is working but I'm sure that this is the wrong way.. maybe there is a better way to manipulate the result of function(date). So is there a way to make this to works without using eval?
flatpickr("#data-partenza", {
locale:'it',
minDate: "2020-07-16",
enable: [
function(date) {
// return true to enable
var drop_destinazione = jQuery('[name="destinazione"]').val();
var result = '';
var dateCorfu = ["2020-07-16","2020-07-23","2020-07-30","2020-08-06","2020-08-13","2020-08-20"];
var dateZante = ["2020-07-17","2020-07-24","2020-07-31","2020-08-07","2020-08-14"];
var datePag = ["2020-07-18","2020-07-25","2020-08-01","2020-08-08"];
var slice = 'date.toISOString().slice(0,10)';
var i;
if(drop_destinazione == 'Corfù'){
for (i = 0; i < dateCorfu.length; i++) {
result += (slice + '==' + '"' + dateCorfu[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else if(drop_destinazione == 'Zante'){
for (i = 0; i < dateZante.length; i++) {
result += (slice + '==' + '"' + dateZante[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else if(drop_destinazione == 'Pag'){
for (i = 0; i < datePag.length; i++) {
result += (slice + '==' + '"' + datePag[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else {
console.log('no destination selected')
}
}
],
dateFormat: "d-m-Y",
disableMobile: true,
});
since you are only doing if-validations, why dont you just immediately evaluate and accumulate at each result += ..?
result = false;
for (...) {
if (condition) result = true;
}
return result;
or even better: exit early like this:
result = true;
for (...) {
if (condition) return true;
}
return false;
applied to your original code this would make your function look like this:
function(date) {
var drop_destinazione = jQuery('[name="destinazione"]').val();
var dateCorfu = ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"];
var dateZante = ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"];
var datePag = ["2020-07-18","2020-07-25","2020-08-01","2020-08-08"];
var slice = date.toISOString().slice(0, 10);
if (drop_destinazione == 'Corfù') {
for (var i = 0; i < dateCorfu.length; i++) {
if (slice == dateCorfu[i]) return true;
}
}
else if(drop_destinazione == 'Zante') {
for (var i = 0; i < dateZante.length; i++) {
if (slice == dateZante[i]) return true;
}
}
else if(drop_destinazione == 'Pag') {
for (var i = 0; i < datePag.length; i++) {
if (slice == datePag[i]) return true;
}
}
else { console.log('no destination selected'); }
return false;
}
however there are steps you can take to make your code less repetitive:
function(date) {
var drop_destinazione = jQuery('[name="destinazione"]').val();
var slice = date.toISOString().slice(0, 10);
var allowed = {
Corfù: ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"],
Zante: ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"],
Pag: ["2020-07-18","2020-07-25","2020-08-01",
"2020-08-08"],
};
if (allowed[drop_destinazione] == undefined) {
console.log('no destination selected');
return false;
}
return allowed[drop_destinazione].indexOf(slice) !== -1;
}
of course the property name "Corfù" does not look too nice, however "drop_destinazione" seems to be a dropdown, these have both a value and a label (see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select). you should make the values simple strings like "corfu":
<select>
<option value="corfu">Corfù</option>
...
</select>
if you do it like this, you can make the allowed index look nicer:
var allowed = {
corfu: ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"],
zante: ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"],
pag: ["2020-07-18","2020-07-25","2020-08-01",
"2020-08-08"],
};
hope this helps!

JavaScript. Please advise on better code reuse and/or structure

As the title suggests, A better coding structure or implementation for my JavaScript below. This checks a ID element values from a form before submitting to a database.
I'm interested to know if I could have reduced the code size/could have implemented reuse of code which will give me some tips for the future!
Thanks.
function validateRunnerID()
{
var runnerID = document.getElementById('RunnerID').value;
if (isNaN(runnerID) || runnerID < 1 || runnerID > 9999)
{
return "RunnerID: Enter a Integer Value between 1-9999 \n\n";
}else{
return "";
}
}
function validateEventID()
{
var eventID = document.getElementById('EventID').value;
if (isNaN(eventID) || eventID < 1 || eventID > 9999)
{
return "EventID: Enter a Integer Value between 1-9999 \n\n";
}else{
return "";
}
}
function validateDate()
{
var checkDate= /^[0-9]{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])/;
var date= document.getElementById('Date');
var tof= date.value.match(checkDate);
return tof? "" : "Date: Enter a Valid Date with parameters: YYYY-MM-DD \n\n";
}
function validateFinishTime()
{
var finishTime = document.getElementById("FinishTime").value;
if (finishTime.match(/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/))
{
return ""
}else{
return "Finish Time: Enter a valid Time with parameters: HH:MM:SS \n\n";
}
}
//
//
function validatePosition()
{
var position = document.getElementById('Position').value;
if (position.length == 0)
{
document.getElementById('Position').value = -1;
return "";
}else{
return "";
}
}
function validateCategoryID()
{
var categoryID = document.getElementById('CategoryID').value;
if (categoryID.length == 0)
{
document.getElementById('CategoryID').value = -1;
return "";
}else{
return "";
}
}
function validateAgeGrade()
{
var ageGrade = document.getElementById('AgeGrade').value;
if (ageGrade.length == 0)
{
document.getElementById('AgeGrade').value = -1;
return "";
}else{
return "";
}
}
function validatePB()
{
var pBest = document.getElementById('PB').value;
if (pBest.length == 0)
{
document.getElementById('PB').value = 0;
return "";
}else{
return "";
}
}
//
//
function validateForm()
{
var result = validateRunnerID() + validateEventID() + validateDate() + validateFinishTime() + validatePosition() + validateCategoryID() + validateAgeGrade() + validatePB();
if ( result == "" )
{
alert("Data Accepted and Submitted \n\n");
return true;
}else{
alert("Please Fix Errors Listed: \n\n" + result);
return false;
}
}
One thing you can do is to accept an elementId as input to your validation functions. This allows to reuse the same logic for different fields.
For example:
function validate4DigitInt(elementId)
{
var value = document.getElementById(elementId).value;
if (isNaN(value) || value < 1 || value > 9999)
{
return elementId + ": Enter a Integer Value between 1-9999 \n\n";
}else{
return "";
}
}
Now you can validate both RunnerId and EventId using the same function:
var result="";
result+=validate4DigitInt("RunnerId");
result+=validate4DigitInt("EventId");

Search, count duplicated strings and add for each numbers

I have a script that is searching for duplicated text strings in an array and changing the colors.
function checkDuplicates() {
var values = new Array();
var $input = $('input[type=\'text\']');
var error = 0;
$input.each(function() {
$(this).removeClass('double-error');
var that = this;
if (that.value!='') {
values[that.value] = 0;
$('input[type=\'text\']').each(function() {
if (this.value == that.value) {
values[that.value]++;
}
});
} //endif
});
$input.each(function(key) {
if (values[this.value]>1) {
error++;
$(this).addClass('double-error');
}
});
return (error <= 0); //returns false or true
}
<style type="text/css">
.double-error {
color:red;
border:1px solid red;
}
</style>
This is working fine.
However, I need to count duplicated strings and add keep track of whether they are the first occurence of that word, the second occurence of that word, etc.
For example:
Given john, john, peter, doe, peter, john, the result would be john-1, john-2, peter-1, doe, peter-2, john-3.
This is what I currently have:
function eliminateDuplicates() {
var values = new Array();
var $input = $('input[type=\'text\']');
var error = 0;
$input.each(function() {
$(this).removeClass('double-error');
var that = this;
if (that.value!='') {
values[that.value] = 0;
$('input[type=\'text\']').each(function() {
if (this.value == that.value) {
values[that.value]++;
}
});
}
});
$input.each(function(key) {
if (values[this.value]>1) {
error++;
myArray = values[this.value];
for (var i = 0; i < myArray; i++) {
$(this).parent()
.find('input[type=\'text\']')
.val(this.value + '-' + i);
}
}
});
return error <= 0; //return error > 0 ? false : true;
}
But I got this result:
john-0-1-2, john-0-1-2, peter-0-1, doe, peter-0-1, john-0-1-2
What's wrong?
I make some modification:
function eliminateDuplicates() {
var values = new Array();
var $input = $('input[type=\'text\']');
var error = 0;
$input.each(function() {
$(this).removeClass('double-error');
var that = this;
if (that.value!='') {
values[that.value] = 0;
$('input[type=\'text\']').each(function() {
if (this.value == that.value) {
values[that.value]++;
}
});
}
});
$input.each(function(key) {
if (values[this.value]>1) {
var name=this.value;
var names = values[this.value];
values[this.value]++;
for (var i = 0; i < names; i++){
$(this).parent().find('input[type=\'text\']').val(name + '-' + i);
}
}
});
checkDoubles();
return error <= 0; //return error > 0 ? false : true;
}
now I getting counts in sequence but not from 1.
for example if I have 4 duplicated names (Peter) i getting:
Peter-3, Peter-4, Peter-5, Peter-6.
but I need
Peter-1, Peter-2, Peter-3, Peter-4.
what wrong?
I think you're looking for something like this:
function eliminateDuplicates() {
var repeats = {};
var error = false;
//cache inputs
var $inputs = $("input[type='text']");
//loop through inputs and update repeats
for (i = 0; i < $inputs.length; ++i) {
//cache current element
var cur = $inputs[i];
//remove class
$(cur).removeClass("double-error");
//get text of this element
var text = $(cur).val();
//no text -- continue
if (text === "") {
continue;
}
//first time we've came across this value -- intialize it's counter to 1
if ((text in repeats) === false) {
repeats[text] = 1;
}
//repeat offender. Increment its counter.
else {
repeats[text] = repeats[text] + 1;
}
//update the the value for this one
$(cur).val(text + "-" + repeats[text]);
}
return error; // always returns false since I'm not sure
// when it's supposed to return true.
}
PS: I didn't understand when error was supposed to be true, so it's always false. Nevertheless, this should be enough to get you going.
PPS: Plunker here.

How to know if there's a value inside an array of object in javascript?

I have this array of object:
[Object, Object]
0: Object
{
date: ""
number: undefined
}
1: Object
{
date: ""
number: undefined
}
It always said required if that value is not empty. Maybe someone can help me with much more knowledgeable about this.
Here's my code:
$(function(){
var len = $('#groupContainer > div').length;
var arr = [];
for(var i=0; i < len; i++){
var number = $('#number_' + [i + 1]);
var date = $('#date_' + [i + 1]);
console.log(number)
var a = number.map(function(){
return this.value;
});
var b = date.map(function(){
return this.value;
});
var newObj = {number: a[0], date: b[0]}
arr.push(newObj);
}
for(var c = 0; c < arr.length; c++)
{
var count = c + 1;
var message ="";
for(var d in arr[c])
{
if(arr[c].hasOwnProperty(d))
{
if(arr[c][d] == "")
{
message = d + ' is required!';
}
message += message + "\n";
}
}
alert('Group: ' + count + ' ' + message + '\n');
}
});
Demo
The check on emptiness appears to work correctly. Both fields in "Group 1" have a value and its message doesn't mention either as "required."
Though, you have an issue with how the message is being built, reporting a single property at least twice:
"Group: 2 date is required!date is required!"
This is due to these modifications of message:
if(arr[c][d] == "")
{
message = d + ' is required!';
}
message += message + "\n";
The first line modifying the message, by using the assignment operator (=), will discard any previous value that message may have held.
var message = "something previous"
message = 'property' + ' is required!';
console.log(message); // "property is required!"
The other line then duplicates the contents of message, appending it to itself:
// same as `message = message + message + "\n";`
message += message + "\n";
console.log(message); // "property is required!property is required!\n"
How you could revise this is to modify message only when an empty field is found and concatenate onto the previous value with what's being added.
if(arr[c][d] == "")
{
message += d + ' is required!\n';
// ^ concatenate onto the previous `message` value
// including the `\n` here
}
// remove the other modification
http://jsfiddle.net/b60981ku/
You can check whether the variable is null or empty by,
arr[c][d] == null || arr[c][d].length <= 0
If I am not mistaken what you're trying to achieve..
FIDDLE
Use a Custom validation
From what i understand after our small comment dialog, you should implement a custom validation like the one in the following function
function isObjectNullOrEmpty(obj) {
if (!obj) {
return true;
}
var requiredKeys = ['name'];
for (var i in requiredKeys) {
var key = requiredKeys[i];
var value = obj[key];
if (value === undefined || value === null) {
return true;
}
if ((typeof value === 'string' || value instanceof String) && !value.trim()) {
return true
}
}
return false;
}
http://jsfiddle.net/nknaftq3/
$(function () {
var object1 = {
name: ''
};
alert(JSON.stringify(object1) + ' \n\nresult : ' + isObjectNullOrEmpty(object1));
var object2 = {
name: 'asd'
};
alert(JSON.stringify(object2) + ' \n\nresult : ' + isObjectNullOrEmpty(object2));
});

Javascript program keeps outputting wrong index of array

I'm trying to finish an assignment, I'm stuck at and can't find a solution.
Below is my full code.
//Student Object
var student = {
f_name: "",
l_name: "",
s_numb: "",
email: "",
courses: [],
/*This function returns if current object has a specific course
and returns true if it does and false if not.*/
hasCourse: function (course) {
for (var c = 0; c < this.courses.length; c++) {
if (course == this.courses[c]) {
return true;
}
}
return false;
}
};
/*This function returns name with first letter
capitalized and the rest lowercase.*/
function formatingName(name) {
return name.charAt(0).toUpperCase() + name.substr(1, name.length);
}
/*This function validates to match the Student ID pattern and
returns true it matches and false if not.*/
function validateStudentID(sid) {
var patt = /^([0-9]{3}[.]){2}[0-9]{3}$/;
return patt.test(sid);
}
/*This function receives a string array of course codes which
are to be registered for a student. The function returns an empty
string indicating all course codes in the array are valid; otherwise
the function returns the first invalid course code in the array.*/
function validateCourses(courses) {
var error = false;
for (i = 0; i < courses.length; i++) {
if (error == false) {
if (courses[i] != "APC100" && courses[i] != "IPC144" &&
courses[i] != "ULI101" && courses[i] != "IOS110" &&
courses[i] != "EAC150" && courses[i] != "IBC233" &&
courses[i] != "OOP244" && courses[i] != "DBS201" &&
courses[i] != "INT222") {
error = courses[i];
break;
}
}
}
if (error != false) {return error;} else {return "";}
return '';
}
var response = true; //Continues to prompt if error is true
var error = false; //Error flag
var temp_obj = []; //Temporary object that hold current object's values
var temp_course = [];
var students = [];
var x = 0;
while (response == true) {
do {
var str = prompt("Please enter first name, last name, student ID,\nemail and courses (separated by ',')");
if (str == "" || str === null) {
response = false;
break;
}
//Removing white spaces in the string
str = str.split(' ').join('');
//Splitting the string into array by , (coma) and assigning it to temporary object array
temp_obj = str.split(',');
//Validating Student ID
if (validateStudentID(temp_obj[2]) == false) {
alert(temp_obj[2] + " is not a valid student ID, Please use xxx.xxx.xxx format.\nPlease try again!");
error = true;
}
//Validating if student is registered in atleast 1 course.
if (temp_obj.length < 5) {
alert("A student must be registered in at-least 1 course");
error = true;
}
//Checking if student is registered in more than 6 courses
if (temp_obj.length > 10) {
temp_obj = temp_obj.slice(0,9);
}
//Extracting courses from temporary object array
temp_course = temp_obj.slice(4, temp_obj.length);
//Makking all the courses uppercase
for (i = 0; i < temp_course.length; i++) {
temp_course[i] = temp_course[i].toUpperCase();
}
//Validating if courses are valid
if (validateCourses(temp_course) != "") {
alert(validateCourses(temp_course) + " is not the course provided by CPD program!\nPlease try again.");
error = true;
}
}
while (error == true);
//Break out of loop if user submitted nothing or if user pressed cancel
if (response == false) {break;}
//Merging cources array back with temporary object array
temp_obj = temp_obj.concat(temp_course);
//Creating a new instance of a student
students[x] = Object.create(student);
//Assigning values to student object from temporary object;
students[x].f_name = formatingName(temp_obj[0]); //Formatting name
students[x].l_name = formatingName(temp_obj[1]);
students[x].s_numb = temp_obj[2];
students[x].email = temp_obj[3].toLowerCase(); //Making the email all lowercase
//Making the course codes in Uppercase
for (i = 0; i < (temp_obj.length) - 4; i++ ) {
students[x].courses[i] = temp_obj[i + 4].toUpperCase();
}
x++;
}
//Printing total registered students
alert("There are total " + students.length + " students registered.");
var R_fname = [];
var R_lname = [];
var R_sid = [];
var R_email = [];
do {
var no_error = false;
var query = true;
var query_course = [];
while (no_error == false) {
query = prompt("Please enter a course code:");
if (query == "" || query == null) {
query = false;
break;
}
no_error = true;
query_course[0] = query.toUpperCase();
if (validateCourses(query_course) != "") {
alert(query + " is not the course provided by CPD program!\nPlease try again");
no_error = false;
}
}
if (query == false) {break;}
//THIS IS WHERE I THINK THE PROBLEM IS
//THIS IS WHERE I THINK THE PROBLEM IS
//THIS IS WHERE I THINK THE PROBLEM IS
//THIS IS WHERE I THINK THE PROBLEM IS
for (var a = 0; a < students.length; a++) {
//Checking if student is registred in a course
if (students[a].hasCourse(query_course) == true) {
//Assigning values to temporary array.
R_fname[a] = students[a].f_name;
R_lname[a] = students[a].l_name;
R_sid[a] = students[a].s_numb;
R_email[a] = students[a].email;
}
}
var fin_str = "";
//Concatenating all the students in a specific course to fin_str as string.
for (var b = 0; b < R_fname.length; b++) {
fin_str += (R_fname[b] + " " + R_lname[b] + " " + R_sid[b] + " " + R_email[b] + " \n");
}
//Printing list of student in a specific course
alert("List of students registered in " + query + "\n\n" + fin_str);
//Retting temporary arrays
R_fname.length = 0;
R_lname.length = 0;
R_sid.length = 0;
R_email.length = 0;
//Confirms to Exit the query loop
if (confirm("Click 'OK' to continue to query class lists.\nClick 'Cancel' to stop the program.") == false) {break;}
}
while (query != false);
These are the test values:
roy,bean,056.171.486,rbean#example.ca,int222
carl,bell,121.126.536,cbell#example.ca,dbs201,int222
eric,brand,046.123.976,ebrand#example.ca,oop244,dbs201,int222
henry, clay, 034.146.412, hclay#example.ca , ibc233 , oop244 , dbs201 , int222
When the program asks to enter the course code; it is suppose to see if the students have that course and only if they do, it prints that students info.
In my case, even if student does not have the course it still prints it.
Please run the code to see if it makes more sense... I can't explain any better
The problem can be reduced to this:
var Foo = {
courses: []
};
var x = Object.create(Foo);
var y = Object.create(Foo);
x.courses.push(123);
alert(y.courses[0]); // "123"
The reason for this behaviour is that both objects inherit the same prototype and any changes made to .courses will apply to both objects.
For this reason, it would be better to create a constructor function instead:
function Foo()
{
this.courses = [];
}
var x = new Foo();

Categories