matching two fields in a form from two functions in javascript - javascript

I have two fields that I'd like to match. (already done the validation functions for field 1 and 2)
field01 has a client number Txxxxx xxxxx (can be T G or M)
field02 has the area code 416 / 905 / 647
I'd like to match T with 416, G with 905, and M with 647.
and show a relationship error if the rules were broken.
I made a separate function trying to compare the two.
function validatecompare(errMessages)
{
var clientID = document.pizza.field02;
var telenum = document.pizza.field03;
var client = clientID.value;
var phone = telenum.value;
var firstL = "";
var areaC = "";
firstL=client.substr(0,1);
areaC =phone.substr(0,3);
if ((firstL) !=areaC)
{
errMessages += "<li>Client Number and Telephone No. are not consistent with our set up rules.</li>\n";
}
return errMessages;
}
I know that's wrong, I just have no idea how to compare two fields from two separate functions. The error message will pop up regardless of what I do. Even if I violate the rules for field 1 and 2 the error message will pop up with those when it shouldn't.
If there is somewhere I can read up on how to do this would be excellent for future reference.
any help would be greatly appreciated, thanks.

You're literally comparing 416 and T. You need some kind of lookup table:
function validatecompare(errMessages) {
var clientID = document.pizza.field02;
var telenum = document.pizza.field03;
var client = clientID.value;
var phone = telenum.value;
var firstL = client.charAt(0);
var areaC = phone.substr(0, 3);
var areaCodes = {
'416': 'T',
'905': 'G',
'647': 'M'
};
if(firstL !== areaCodes[areaC]) {
errMessages += "<li>Client Number and Telephone No. are not consistent with our set up rules.</li>\n";
}
return errMessages;
}

Related

How to write (SetValues) to a Google Sheet using a filtered forEach loop?

I've been trying for hours to make the following Google Apps Script work. What it needs to do, is send emails (from an html-template) to anyone that:
has a complete Event Schedule (which is completed if they have been
assigned to at least 4 events, which is counted in column Q);
has NOT been sent an email earlier (which is kept track of in column
R);
The script keeps track of errors in column S, i.e. if there's no email address provided.
It appears it only works:
if I comment out
data = data.filter(function(r){ return r[17] == true & r[16] > 3});
or if I comment out
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
How can I get this script to work properly?
A copy of the Google Sheet I'm referring to is this one:
https://docs.google.com/spreadsheets/d/1sbOlvLVVfiQMWxNZmtCLuizci2cQB9Kfd8tYz64gjP0/edit?usp=sharing
This is my code so far:
function SendEmail(){
var voornaam = 3;
var achternaam = 4;
var email = 5;
var event1 = 9;
var event2 = 10;
var event3 = 11;
var event4 = 12;
var event5 = 13;
var event6 = 14;
var event7 = 15;
var emailTemp = HtmlService.createTemplateFromFile("email");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Events Day 1");
var datum = ws.getRange(1,3).getValue();
var spreker = ws.getRange(1,6).getValue();
var data = ws.getRange("A3:R" + ws.getLastRow()).getValues();
data = data.filter(function(r){ return r[17] == false && r[16] > 3}); //Either this needs to be commented out...
let errors = [];
let mailSucces = [];
data.forEach(function(row){
try{
emailTemp.voornaam = row[voornaam];
emailTemp.email = row[email];
emailTemp.datum = datum;
emailTemp.spreker = spreker;
emailTemp.event1 = row[event1];
emailTemp.event2 = row[event2];
emailTemp.event3 = row[event3];
emailTemp.event4 = row[event4];
emailTemp.event5 = row[event5];
emailTemp.event6 = row[event6];
emailTemp.event7 = row[event7];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(
row[email],
"Here you go! Your personal schedule for the event of " + datum,
"Your emailprogramm doesn't support html.",
{
name: "Event Organisation Team", htmlBody: htmlMessage, replyTo: "info#fakeemail.com"
});
errors.push([""]);
mailSucces.push(["TRUE"]);
}
catch(err){
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
}); //close forEach
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors); //or this and the next line need to be commented out.
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
}
Edit I have been trying and thinking en trying... but still haven't found out how to make it work. But I also got understanding of why it's not working; I just don't know how to get it fixed.
Let me elaborate on the problem a bit more:
The problem is, that within the forEach loop the range is a filtered variant of the data, pulled from the spreadsheet with getValues. Therefore, writing data back with ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces); results in mismatched checkmarks in te spreadsheet.
So, somehow I need to put the range of the previous used filter data = data.filter(function(r){ return r[17] == false & r[16] > 3}); in a variable...? I guess?
Furthermore, I don't think it's wise to use setValue within the loop, because (from what I understand from my searching on the topic) this results in a slow script, because every loop the script makes an API call to write in the spreadsheet. Hence the errors.push and mailSucces.push, and my attempt to do a setValue at the end, after the loop is finished.
Can someone help me to finish this problem?
The problem is different size of the range you write to and data you are writing in.
Try replacing:
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
With:
ws.getRange(3, 19, errors.length, 1).setValues(errors);
ws.getRange(3, 18, mailSucces.length, 1).setValues(mailSucces);
You should use this variation of getRange
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getrangerow,-column,-numrows,-numcolumns
Your data has non-fixed number of rows and fixed number of columns (1). In general case your data will be matrix of X rows and Y columns. For that purpose you can make it completely dynamic:
sheet.getRange(startRow, startColumn, data.length, data[0].length)
Just make sure data.length is > 0 before you do this, otherwise data[0].length will break.
Edit:
I started writing a comment but it got too long. There are couple of things that may go wrong with sending emails. First thing I noticed is that you use & in filter, but in AppsScript/JavaScript/C-like-languages, you should use && for logical AND. Now the email: you only detect the code break with the catch block. At this point you don't know why the code breaks it could be anything. With GmailApp I recommend you to use createDraft while developing, then when all ok replace it with sendEmail for the final version, both functions have the exact same parameters, thank you Google devs ;-).
To find out the exact problem you should get the error message on break and display it. err.stack should tell you pretty much everything:
catch(err){
Logger.log(err.stack); // Added
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
Run the sendEmail function from the code editor and you should see the Log for each catch(err) pass.

Javascript Function to Obscure Email Using Asterisks?

I'm working on a password reset page where a user types in their username. I'd like to let them know what email it was sent to (sometimes we forget what email we used), without revealing too much information.
So rather than showing: joe_awesome#example.com I'd like to do the following: jo*********#example.com in javascript.
How would I do this efficiently? Basically I'd only like to show the first two letters and the domain only.
P.S. I'm new to javascript. Thanks!
Assuming your email is well formatted and the name has at least 3 characters the solution bellow should work.
var email = "joe_awesome#example.com";
function formatEmail(emilString){
var splitEmail = emilString.split("#")
var domain = splitEmail[1];
var name = splitEmail[0];
return name.substring(0,3).concat("*********#").concat(domain)
}
console.log(formatEmail(email));
In case you want the strings to have the same lengths although i don't recommend it.
function formatEmailSameLength(emilString){
var splitEmail = emilString.split("#")
var domain = splitEmail[1];
var name = splitEmail[0];
return name.substring(0,3).concat(Array(name.length-3).join("*")).concat("#").concat(domain)
}
Just a different answer
const maskEmail = (mail) => {
let mailUsername = mail.split("#")[0];
mailUsername = mailUsername[0] + mailUsername.substring(1).replace(/./gi, '*')
let mailDomain = mail.split("#")[1].split(".")[0].replace(/./gi, '*');
let mailTld = mail.split("#")[1].split(".")[1].replace(/./gi, '*')
return `${mailUsername}#${mailDomain}.${mailTld}`
}

Locating MAX Number in a string for a list of records

I am relatively new to JavaScript and trying to get the following achievement.
Lets say we have the following data records.
Example data records:
A_ID_R1_V1
A_ID_R1_V2
A_ID_R2_V1
Basically I am looking for two results:
1.Create a string based on record A_ID_R1_V2.
Input = A_ID_R1_V2
Output = A_ID_R1_V3
My thoughts about this is so locate the MAX V<#> for A_ID_R1_ and then add 1.
2.Create a string based on record A_ID_R2_V1.
Input = A_ID_R2_V1
Output = A_ID_R3_V1
My thoughts about this is so locate the MAX R<#> for all records and then add 1.
Thanks a lot in advance!!!!!!!!
I have strong feeling that this is some kind of school homework...
Anyhow, this will do the job, but its not sophisticated nor very effective
function updateId(letter){
var pos = (letter === 'V')?3:2;
var parts = id.split('_');
var num = parseInt(parts[pos].substring(1,parts[pos].length));
parts[pos] = letter+(num+1);
id = parts.join('_');
logVal(id);
}
try this with regex: http://jsfiddle.net/mig1098/wh6n2oqL/
newEntry = function(entry){
var str2 = entry.replace(/\d+$/,'');
var num = parseInt(entry.replace(/A_ID_R(\d+)_V/,''));
num = num+1;
return str2+num;
}

Regex not matching properly

Ive been working on this regex for days now and I cant get it figured out. It either passes everything I put in there or it kicks everything out and I cannot seem to make it function. Admittedly I am new to doing this complex of stuff with Javascript so It may be that you realy cant do this.
I want to check onkeypress what was entered into the input and then validate it to x, y, or z. Then from there send it on about its way to do other neat stuff.
So the question is what the heck am I not understanding about RegExp?
Here is a FIDDLE for it.
function val() {
var gradeIn = document.querySelectorAll("#letGrade input[type=text]");
var checkGrade = new RegExp(/[xyz]/gi);
for (var i = 0; i < gradeIn.length; i++) {
if (!checkGrade.test(gradeIn.value)) {
alert ("This must be X, Y, or Z");
return false;
} else {
return true;
}
}
};
EDIT/UPDATE:
I was trying to do this on keypress and validate each text input individualy however this was realy kinda squishy in the grand scheme of things and not working out exactly correct. I decided to validate all text inputs onsubmit and have everything go all at once. Updated code is below.
function calcGPA() {
var grades = document.querySelectorAll("#letGrade input[type=text]");
var contacts = document.querySelectorAll("#conHours input[type=text]");
var gVals = [];
var cVals = [];
var failGrade = "The Letter Grade input may only be A, B, C, D or F";
var failHours = "The Contact Hours input may only be 1, 2, 3, 4 or 5";
var checkGrade = /^[ABCDF]/;
var checkhours = /^[12345]/;
for (var i = 0; i < grades.length; i++) {
if (!checkGrade.test(grades[i].value)) {
alert(failGrade);
return false;
}
if (!checkhours.test(contacts[i].value)) {
alert(failHours);
return false;
}
gVals.push(grades[i].value);
cVals.push(contacts[i].value);
}
//Other cool stuff happens here
};
Now to just finish the conversion piece for the letters to numbers and the math piece. Thank you for your help on this!
The problem's not only with your regular expression.
if (!checkGrade.test(gradeIn[i].value)) {
You weren't checking each grade. Now if you want it to only be those characters, you have to extend the regular expression a bit. Also, there's no point calling new RegExp if you're using native syntax.
var checkGrade = /^[xyz]+$/;
That means that you're OK with the fields being like "xxyyz" or "zzy". If it should just be one character, that'd be
var checkGrade = /^[xyz]$/;

Qualtrics Javascript questions - Matrix Tables

I'm having some issues in Qualtrics with certain functions that are easy enough in a single question, but become impossible when using a Matrix Table or a Side-by-Side.
1) Content validation for individual fields in the Matrix Table - currency in the Matrix table, you can only check validation for multiple fields and generate a single error.
2) Required Response for a field based on an entry in the previous field in that row of the Matrix Table
3) Recode Values of text entries in a Matrix Table - there doesn't seem to be a way to this in a Matrix Table. Again, it's very simple to do with a single question.
Basically, I'd like a user to be able to complete only a single row of the Matrix Table if they want, but for the rows they complete, I need to validate specific fields and require response for specific fields, and possibly re-code their text entries.
Is there an easy way to do this with Javascript instead?
Thanks...
My guess is that JavaScript will take care of it. I've had to write several scripts because the validation features in Qualtrics are limited, to say the least.
Depending on how your Qualtrics validations options are set up you'll probably have to use functions from Qualtrics' JavaScript. Below is the basic structure you would use. Not really knowing anything about your Qualtrics question ids, I used placeholders.
Update: I would recommend using the side-by-side question type.
Here's a
link to the question/survey
To get you started off, here is the code for the first student. You need to copy the same pattern for students 2-5. You can go so many ways with validation style (in-line messages, pop-ups) that I didn't even go there. The email validation you can choose in Qualtrics under content validation for the two email columns. You can also choose phone number validation as well. The validation here will just prevent a user from going to the next page until they meet all the criteria. You could explain the validation criteria in the body of the question.
The questions ids I used are listed first and correspond exactly to the placement of the items in the screen shot except for the Y/N question which is different for a side-by-side question and has the id QR~QID9#5~1~1 for yes and QR~QID9#5~1~2 for no. I don't know what your skills are regarding Firebug but you will need to find the ids that pertain to your specific questions and replace the ones below with them.
I would also recommend using Embedded Data variables to feed in the answers so that you have nice clean legible data in your download. From what I remember, the structure of Qualtrics matrix and side-by-side data are not very usable.
Hopefully, this makes sense to you. If not, ask. I know from personal experience how frustrating it is to find javascript support for Qualtrics.
Qualtrics.SurveyEngine.addOnload(function () {
/*Place Your Javascript Below This Line*/
//QR~QID9#1~1~1~TEXT - QR~QID9#2~1~1~TEXT - QR~QID9#3~1~1~TEXT - QR~QID9#4~1~1~TEXT - QR~QID9#5~1~1/QR~QID9#5~1~2 - QR~QID9#6~1~1~TEXT
//QR~QID9#1~2~1~TEXT - QR~QID9#2~2~1~TEXT - QR~QID9#3~2~1~TEXT - QR~QID9#4~2~1~TEXT - QR~QID9#5~2~1/QR~QID9#5~2~2 - QR~QID9#6~2~1~TEXT
//QR~QID9#1~3~1~TEXT - QR~QID9#2~3~1~TEXT - QR~QID9#3~3~1~TEXT - QR~QID9#4~3~1~TEXT - QR~QID9#5~3~1/QR~QID9#5~3~2 - QR~QID9#6~3~1~TEXT
//QR~QID9#1~4~1~TEXT - QR~QID9#2~4~1~TEXT - QR~QID9#3~4~1~TEXT - QR~QID9#4~4~1~TEXT - QR~QID9#5~4~1/QR~QID9#5~4~2 - QR~QID9#6~4~1~TEXT
//QR~QID9#1~5~1~TEXT - QR~QID9#2~5~1~TEXT - QR~QID9#3~5~1~TEXT - QR~QID9#4~5~1~TEXT - QR~QID9#5~5~1/QR~QID9#5~5~2 - QR~QID9#6~5~1~TEXT
var notvalidphbook1 = 0, notvalidphbook2 = 0, notvalidphbook3 = 0, notvalidphbook4 = 0, notvalidphbook5 = 0;
var phsbooks; //gets sum of notvalidphbook items
var bookrecode1, bookrecode2, bookrecode3, bookrecode4, bookrecode5;
var notvalidemail1 = 0, notvalidemail2 = 0, notvalidemail3 = 0, notvalidemail4 = 0, notvalidemail5 = 0;
var emails; //gets sum of notvalidemail items
var validates; //validation variable that decides if user proceeds or not
Qualtrics.SurveyPage.Question.prototype.validate = function (element) {
//Student name entered
var student1y = $('QR~QID9#1~1~1~TEXT').getValue();
var student2y = $('QR~QID9#1~2~1~TEXT').getValue();
var student3y = $('QR~QID9#1~3~1~TEXT').getValue();
var student4y = $('QR~QID9#1~4~1~TEXT').getValue();
var student5y = $('QR~QID9#1~5~1~TEXT').getValue();
//Student phone number
var student1phone = $('QR~QID9#2~1~1~TEXT').getValue();
var student2phone = $('QR~QID9#2~2~1~TEXT').getValue();
var student3phone = $('QR~QID9#2~3~1~TEXT').getValue();
var student4phone = $('QR~QID9#2~4~1~TEXT').getValue();
var student5phone = $('QR~QID9#2~5~1~TEXT').getValue();
//Emails match
var student1emailA = $('QR~QID9#3~1~1~TEXT').getValue();
var student1emailB = $('QR~QID9#4~1~1~TEXT').getValue();
var student2emailA = $('QR~QID9#3~2~1~TEXT').getValue();
var student2emailB = $('QR~QID9#4~2~1~TEXT').getValue();
var student3emailA = $('QR~QID9#3~3~1~TEXT').getValue();
var student3emailB = $('QR~QID9#4~3~1~TEXT').getValue();
var student4emailA = $('QR~QID9#3~4~1~TEXT').getValue();
var student4emailB = $('QR~QID9#4~4~1~TEXT').getValue();
var student5emailA = $('QR~QID9#3~5~1~TEXT').getValue();
var student6emailB = $('QR~QID9#4~5~1~TEXT').getValue();
//Student book needs
var student1booky = $('QR~QID9#5~1~1').getValue();
var student1bookn = $('QR~QID9#5~1~2').getValue();
var student2booky = $('QR~QID9#5~2~1').getValue();
var student2bookn = $('QR~QID9#5~2~2').getValue();
var student3booky = $('QR~QID9#5~3~1').getValue();
var student3bookn = $('QR~QID9#5~3~2').getValue();
var student4booky = $('QR~QID9#5~4~1').getValue();
var student4bookn = $('QR~QID9#5~4~2').getValue();
var student5booky = $('QR~QID9#5~5~1').getValue();
var student6bookn = $('QR~QID9#5~5~2').getValue();
//Student book name
var student1bookname = $('QR~QID9#6~1~1~TEXT').getValue();
var student2bookname = $('QR~QID9#6~2~1~TEXT').getValue();
var student3bookname = $('QR~QID9#6~3~1~TEXT').getValue();
var student4bookname = $('QR~QID9#6~4~1~TEXT').getValue();
var student5bookname = $('QR~QID9#6~5~1~TEXT').getValue();
if (student1y == '') {
//alert("no name provided, no other info needed");
//"no name provided, no other info needed"
} else if (student1y != '' && (student1phone == '' || (student1emailA == '' || student1emailB == '') || (student1booky == null && student1bookn == null))) {
//alert("you need to provide a phone number and enter the student's book needs");
notvalidphbook1 = 1;
}
else if (student1y != '' && (student1phone != '' && (student1emailA != '' && student1emailB != '') && (student1booky == null && student1bookn == null))) {
notvalidphbook1 = 0;
else {
//alert("thank you for providing a phone number and specifying book needs");
if (student1booky == 'QR~QID9#5~1~1') {
bookrecode1 = 'Y';
} else {
bookrecode1 = 'N';
}
}
if (student1emailA == '' && student1emailB == '') {
//alert("no email provided, no match needed");
//"no email provided, no match needed"
} else if (student1emailA != '' && student1emailA == student1emailB) {
//alert("the emails match");
//"the emails match"
notvalidemail1 = 0;
} else {
//alert("the emails don't match");
//"the emails don't match"
notvalidemail1 = 1;
}
Qualtrics.SurveyEngine.setEmbeddedData('Student1Name', student1y);
Qualtrics.SurveyEngine.setEmbeddedData('Student1Phone', student1phone);
Qualtrics.SurveyEngine.setEmbeddedData('Student1Email', student1emailA);
Qualtrics.SurveyEngine.setEmbeddedData('Student1Txt', bookrecode1);
Qualtrics.SurveyEngine.setEmbeddedData('Student1TxtName', student1bookname);
phsbooks = notvalidphbook1 + notvalidphbook2 + notvalidphbook3 + notvalidphbook4 + notvalidphbook5;
emails = notvalidemail1 + notvalidemail2 + notvalidemail3 + notvalidemail4 + notvalidemail5;
validates = phsbooks + emails;
if (validates == 0) { //validates only if the sum is equal to zero
return true; //this let's the user continue
} else {
return false; //this prevents the user from proceeding to the next page
}
}
});

Categories