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

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");

Related

Prevent action if input field data is not right. (js)

I am stuck here with some issue. There are 3 two entry boxes: for birthday, an amount and an interest rate (%). If you click on the button, the page will show an overview of the balance until the amount have to be doubled.
So the issue is: When I enter an incorrect date, I get a notification. However, the interest is still calculated afterwards. I want to prevent code from being executed with incorrect input.
document.getElementById("button").onclick = loop;
var inputA = document.getElementById("inputA");
var inputB = document.getElementById("inputB");
var inputC = document.getElementById("inputC");
var result = document.getElementById("result")
function allFunctions() {
correctBirthday()
sum();
rate();
loop();
}
function loop() {
var s = inputB.value;
var r = inputC.value;
var doubleS = s * 2;
while (s < doubleS) {
s = ((r / 100 + 1) * s);
result.innerHTML += s + "<br>";
}
if (inputA.value == '')
{ alert('Please enter a value for input A');
return;
}
}
function correctDate(datum) {
var vorm = /^\d{2}-\d{2}-\d{4}$/;
return vorm.test(datum);
}
function correctBirthday() {
var d = inputA.value;
if ( correctDate(d) == false ) {
alert("The form of the date is incorrect");
return;
}
if ( validDate(d) ) {
result.innerHTML = '';
}
}
function rate() {
var r = rentepercentage.value;
if ( correctRate(r) == true ) {
alert("The form of the amount entered is incorrect");
return;
} else {
result.innerHTML = '';
}
}
function correctRate(rente) {
var vorm = /[a-zA-Z]/;
return vorm.test(rente);
}
function sum() {
var s = bedrad.value;
if ( correctSum(s) === true ) {
alert("The form of the amount entered is incorrect");
return;
} else {
result.innerHTML = '';
}
}
function correctSum(som) {
var vorm = /[a-zA-Z]/;
return vorm.test(som);
}
<! DOCTYPE html>
<html>
<body>
<br>
<input type="text" id="inputA" value="05-06-1986"><br>
<input type="text" id="inputB" value="10"><br>
<input type="text" id="inputC" value="4"><br><br>
<button id="button">Klik</button>
<p> De ingevoerde resultaten: </p>
<p id="result"></p>
<script async src="oefin1.js"></script>
</body>
</html>
So the issue is: When I enter an incorrect date, I get a notification. However, the interest is still calculated afterwards. I want to prevent code from being executed with incorrect input.
In your allFunctions function:
function allFunctions() {
correctBirthday()
sum();
rate();
loop();
}
If correctBirthday returns undefined, allFunctions does not know that it should stop. You have two main options:
Throw an error if the birthday is incorrect, and catch it later:
function allFunctions() {
try {
correctBirthday()
sum();
rate();
loop();
} catch ( error ) {
alert( error.message );
}
}
function correctBirthday() {
var d = inputA.value;
if ( correctDate(d) == false ) {
throw new Error("The form of the date is incorrect");
}
if ( validDate(d) ) {
result.innerHTML = '';
}
}
Let correctBirthday return true or false depending on whether it succeeded, and let allFunctions respond appropriately:
function allFunctions() {
let birthdayIsCorrect = correctBirthday();
if ( !birthdayIsCorrect ) {
return;
)
sum();
rate();
loop();
}
function correctBirthday() {
var d = inputA.value;
if ( correctDate(d) == false ) {
alert("The form of the date is incorrect");
return false;
}
if ( validDate(d) ) {
result.innerHTML = '';
}
return true;
}
EDIT: If you want this behaviour when validDate(d) is false as well, try...
function correctBirthday() {
var d = inputA.value;
if ( correctDate(d) == false ) {
throw new Error("The form of the date is incorrect");
}
if ( !validDate(d) ) {
throw new Error("The date is invalid");
}
result.innerHTML = '';
}
// or...
function correctBirthday() {
var d = inputA.value;
if ( correctDate(d) == false ) {
alert("The form of the date is incorrect");
return false;
}
if ( !validDate(d) ) {
alert("The date is invalid");
return false;
}
result.innerHTML = '';
return true;
}

How to show if date is invalid in 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

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();

multiple validation error for a textbox using jquery

I want to print specific emty error message as well as number error message for the age field while during the button click. for my code only the last error message is diplaying.
This is for Validation Purpose.
<script type="text/javascript">
$(document).ready(function () {
$("#<%=btnSubmit.ClientID %>").click(function () {
var error = 0;
var name = $('#<%=txtName.ClientID%>').val();
if ($.trim(name) == '') {
$('#name_error_msg').text('Name cannot be Empty');
$('#name_error_msg').parent().show();
error = 1;
} else
$('#name_error_msg').text('');
var country = $('#<%=ddlCountry.ClientID%>').val();
if (country == 0) {
$('#country_error_msg').text('Please select the Country');
$('#country_error_msg').parent().show();
error = 1;
}
else
$('#country_error_msg').text('');
var age = $('#<%=txtAge.ClientID%>').val();
if ($.trim(age) == '') {
$('#age_error_msg').text('Invalid Age');
$('#age_error_msg').parent().show();
error = 1;
}
var filter = /^[0-9-+]+$/;
if (!filter.test(age)) {
$('#age_error_msg').text('Invalid Age');
$('#age_error_msg').parent().show();
error = 1;
}
else
$('#age_error_msg').text('');
var emailReg = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
if (!filter.test(emailReg)) {
$('#email_error_msg').text('Invalid email format');
$('#email_error_msg').parent().show();
error = 1;
}
else {
$('#email_error_msg').text('');
}
var email = $('#<%=txtEmail.ClientID%>').val();
if ($.trim(email) == '') {
$('#email_error_msg').text('Email cannot be Empty');
$('#email_error_msg').parent().show();
error = 1;
} else {
$('#email_error_msg').text('');
}
if (!($('#<%=ChkAgree.ClientID%>').is(':checked'))) {
error = 1;
$('#check_error_msg').html("Please Tick the Agree to Terms of Use.");
$('#check_error_msg').parent().show();
}
else
$('#check_error_msg').html(" ");
if (error) {
return false;
} else {
return true;
}
});
});
</script>
All you need to do is, replace:
var age = $('#<%=txtAge.ClientID%>').val();
if ($.trim(age) == '') {
$('#age_error_msg').text('Invalid Age');
$('#age_error_msg').parent().show();
error = 1;
}
var filter = /^[0-9-+]+$/;
if (!filter.test(age)) {
$('#age_error_msg').text('Invalid Age');
$('#age_error_msg').parent().show();
error = 1;
}
else
$('#age_error_msg').text('');
with:
var filter = /^[0-9-+]+$/;
var age = $('#<%=txtAge.ClientID%>').val();
if ( $.trim(age) == '' || !filter.test(age)) {
$('#age_error_msg').text('Invalid Age');
$('#age_error_msg').parent().show();
error = 1;
} else {
$('#age_error_msg').text('');
}
You could create a temp variable to add up each error.
var age_errors = [];
var age = $('#<%=txtAge.ClientID%>').val();
if ($.trim(age) == '') {
age_errors.push('Age is empty');
$('#age_error_msg').parent().show();
error = 1;
}
var filter = /^[0-9-+]+$/;
if (!filter.test(age)) {
age_errors.push('Invalid Age number');
$('#age_error_msg').parent().show();
error = 1;
}
// set the error: empty string or a comma-separated list.
$('#age_error_msg').text(age_errors.join(', '));

Applying multiple select filters on a table in jQuery

I have three select boxes which filter the table on with different criteria. For example, if a user wants to see records with Medium priorities, a Yes On Air Critical & Closed Status. Closed is a data-attribute for every row.
I can do that but my issue is if user wants to select a single filter again, it just shows blank result. Here's the javascript:
$("#input_filter_priority").change(function() {
var data = this.value.split(" ");
var $tr_row = $('#project_table').find("tr:not(.hidden)");
var priority_column = $('#project_table').find("tr :not(.hidden) td:nth-child(5)");
if (this.value == "") {
$tr_row.show();
return;
}
$tr_row.hide();
if (filtered_row !== null) {
filtered_row = filtered_row.filter(function() {
$r = $(this);
if ($r.is(":contains('" + data + "')")) {
return true;
}
return false;
})
.show();
} else {
filtered_row = $tr_row.filter(function() {
$tr_text = $(this).val();
$r = $(this);
if ($r.is(":contains('" + data + "')")) {
return true;
}
return false;
})
.show();
}
});
$("#input_closed_filter").change(function() {
var data = this.value.split(" ");
var $tr_row = $('#project_table').find("tr:not(.hidden)");
if (this.value == "") {
$tr_row.show();
return;
}
$tr_row.hide();
if (filtered_row !== null) {
filtered_row = filtered_row.filter(function() {
$r = $(this);
if ($(this).attr('data-closed').match(data)) {
return true;
}
return false;
})
.show();
} else {
filtered_row = $tr_row.filter(function() {
$tr_text = $(this).val();
if ($(this).attr('data-closed').match(data)) {
return true;
}
return false;
})
.show();
}
});
$("#input_on_air_filter").change(function() {
var data = this.value.split(" ");
var $tr_row = $('#project_table').find("tr ");
var on_air_column = $('#project_table').find("tr td:nth-child(6)");
if (this.value == "") {
$tr_row.show();
return;
}
$tr_row.hide();
if (filtered_row !== null) {
filtered_row = filtered_row.filter(function() {
$r = $(this);
if ($(this).attr('data-critical').match(data)) {
return true;
}
return false;
})
.show();
} else {
filtered_row = $tr_row.filter(function() {
$tr_text = $(this).val();
$r = $(this);
if ($(this).attr('data-critical').match(data)) {
return true;
}
return false;
})
.show();
}
});
What should I do here in case user selects same filter twice or any number of times (Suppose if he changes his mind).
Here's the related JSBin.
Here is a simplified/working version:
var priorityFilterData=null;
var onAirCriticalFilterData=null;
var closedFilterData=null;
function applyFilters(){
var $tr_row = $('#project_table').find("tr");
$tr_row.hide();//hide all rows by default
//Show only the rows that meet each filter condition
$tr_row.filter(function(){
var closedFilterCondition = (closedFilterData === null || $(this).attr('data-closed').match(closedFilterData));
var onAirFilterCondition = (onAirCriticalFilterData === null || $(this).attr('data-critical').match(onAirCriticalFilterData));
var priorityFilterCondition = (priorityFilterData === null || $(this).is(":contains('" + priorityFilterData + "')"));
return closedFilterCondition && onAirFilterCondition && priorityFilterCondition;
}).show();
}
$("#input_closed_filter").change(function() {
closedFilterData = this.value.split(" ");
applyFilters();
});
$("#input_on_air_filter").change(function() {
onAirCriticalFilterData = this.value.split(" ");
applyFilters();
});
$("#input_filter_priority").change(function() {
priorityFilterData = this.value.split(" ");
applyFilters();
});

Categories